Files
Vulkan-Samples/samples/performance/multi_draw_indirect/multi_draw_indirect.h
T
2025-09-04 10:54:47 +08:00

154 lines
4.8 KiB
C++

/* Copyright (c) 2021-2025, Holochip Corporation
*
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 the "License";
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#pragma once
#include "api_vulkan_sample.h"
/**
* @brief Offloading processes from CPU to GPU
*/
class MultiDrawIndirect : public ApiVulkanSample
{
public:
MultiDrawIndirect();
~MultiDrawIndirect() override;
bool prepare(const vkb::ApplicationOptions &options) override;
void render(float delta_time) override;
void finish() override;
private:
enum RenderMode
{
CPU,
GPU,
GPU_DEVICE_ADDRESS
} render_mode = GPU;
struct Vertex
{
glm::vec3 pt;
glm::vec2 uv;
};
struct BoundingSphere
{
BoundingSphere() = default;
explicit BoundingSphere(const std::vector<glm::vec3> &pts);
glm::vec3 center = {0, 0, 0};
float radius = 0;
};
struct GpuModelInformation
{
glm::vec3 bounding_sphere_center;
float bounding_sphere_radius;
uint32_t texture_index = 0;
uint32_t firstIndex = 0;
uint32_t indexCount = 0;
uint32_t _pad = 0;
};
struct SceneUniform
{
glm::mat4 view;
glm::mat4 proj;
glm::mat4 proj_view;
uint32_t model_count;
} scene_uniform;
struct SceneModel
{
std::vector<Vertex> vertices;
std::vector<std::array<uint16_t, 3>> triangles;
size_t vertex_buffer_offset = 0;
size_t index_buffer_offset = 0;
size_t texture_index = 0;
BoundingSphere bounding_sphere;
};
struct Texture
{
std::unique_ptr<vkb::core::Image> image;
std::unique_ptr<vkb::core::ImageView> image_view;
uint32_t n_mip_maps;
};
std::vector<SceneModel> models;
std::unique_ptr<vkb::core::BufferC> vertex_buffer;
std::unique_ptr<vkb::core::BufferC> index_buffer;
std::unique_ptr<vkb::core::BufferC> model_information_buffer;
std::unique_ptr<vkb::core::BufferC> scene_uniform_buffer;
std::vector<Texture> textures;
std::vector<VkDescriptorImageInfo> image_descriptors;
bool m_freeze_cull = false;
bool m_enable_mdi = true;
bool m_requires_rebuild = false;
VkPipeline pipeline{VK_NULL_HANDLE};
VkPipelineLayout pipeline_layout{VK_NULL_HANDLE};
VkDescriptorSetLayout descriptor_set_layout{VK_NULL_HANDLE};
VkDescriptorSet descriptor_set{VK_NULL_HANDLE};
VkSampler sampler_linear{VK_NULL_HANDLE};
VkSampler sampler_nearest{VK_NULL_HANDLE};
// GPU Draw Calls
void run_cull();
void run_gpu_cull();
VkPipeline gpu_cull_pipeline{VK_NULL_HANDLE};
VkPipelineLayout gpu_cull_pipeline_layout{VK_NULL_HANDLE};
VkDescriptorSetLayout gpu_cull_descriptor_set_layout{VK_NULL_HANDLE};
VkDescriptorSet gpu_cull_descriptor_set{VK_NULL_HANDLE};
// Device Address
VkPipeline device_address_pipeline{VK_NULL_HANDLE};
VkPipelineLayout device_address_pipeline_layout{VK_NULL_HANDLE};
VkDescriptorSetLayout device_address_descriptor_set_layout{VK_NULL_HANDLE};
VkDescriptorSet device_address_descriptor_set{VK_NULL_HANDLE};
std::unique_ptr<vkb::core::BufferC> device_address_buffer{nullptr};
std::vector<vkb::core::CommandBufferC> compute_command_buffers{};
const vkb::Queue *compute_queue{nullptr};
std::vector<uint32_t> queue_families;
// CPU Draw Calls
void cpu_cull();
std::vector<VkDrawIndexedIndirectCommand> cpu_commands;
std::unique_ptr<vkb::core::BufferC> cpu_staging_buffer;
std::unique_ptr<vkb::core::BufferC> indirect_call_buffer;
void request_gpu_features(vkb::PhysicalDevice &gpu) override;
void build_command_buffers() override;
void on_update_ui_overlay(vkb::Drawer &drawer) override;
void create_samplers();
void load_scene();
void initialize_resources();
void create_pipeline();
void create_compute_pipeline();
void initialize_descriptors();
void update_scene_uniform();
void draw();
bool m_supports_mdi = false;
bool m_supports_first_instance = false;
bool m_supports_buffer_device = false;
};
std::unique_ptr<vkb::VulkanSampleC> create_multi_draw_indirect();