/* 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 &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 vertices; std::vector> 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 image; std::unique_ptr image_view; uint32_t n_mip_maps; }; std::vector models; std::unique_ptr vertex_buffer; std::unique_ptr index_buffer; std::unique_ptr model_information_buffer; std::unique_ptr scene_uniform_buffer; std::vector textures; std::vector 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 device_address_buffer{nullptr}; std::vector compute_command_buffers{}; const vkb::Queue *compute_queue{nullptr}; std::vector queue_families; // CPU Draw Calls void cpu_cull(); std::vector cpu_commands; std::unique_ptr cpu_staging_buffer; std::unique_ptr 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 create_multi_draw_indirect();