154 lines
4.8 KiB
C++
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();
|