1 /* 2 * Copyright (C) 2016 Google, Inc. 3 * 4 * Permission is hereby granted, free of charge, to any person obtaining a 5 * copy of this software and associated documentation files (the "Software"), 6 * to deal in the Software without restriction, including without limitation 7 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 * and/or sell copies of the Software, and to permit persons to whom the 9 * Software is furnished to do so, subject to the following conditions: 10 * 11 * The above copyright notice and this permission notice shall be included 12 * in all copies or substantial portions of the Software. 13 * 14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 17 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 19 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 20 * DEALINGS IN THE SOFTWARE. 21 */ 22 23 #ifndef SMOKE_H 24 #define SMOKE_H 25 26 #include <condition_variable> 27 #include <memory> 28 #include <mutex> 29 #include <string> 30 #include <thread> 31 #include <vector> 32 33 #include <vulkan/vulkan.h> 34 #include <glm/glm.hpp> 35 36 #include "Simulation.h" 37 #include "Game.h" 38 39 class Meshes; 40 41 class Smoke : public Game { 42 public: 43 Smoke(const std::vector<std::string> &args); 44 ~Smoke(); 45 46 void attach_shell(Shell &sh); 47 void detach_shell(); 48 49 void attach_swapchain(); 50 void detach_swapchain(); 51 52 void on_key(Key key); 53 void on_tick(); 54 55 void on_frame(float frame_pred); 56 57 private: 58 class Worker { 59 public: 60 Worker(Smoke &smoke, int index, int object_begin, int object_end); 61 62 void start(); 63 void stop(); 64 void update_simulation(); 65 void draw_objects(VkFramebuffer fb); 66 void wait_idle(); 67 68 Smoke &smoke_; 69 70 const int index_; 71 const int object_begin_; 72 const int object_end_; 73 74 const float tick_interval_; 75 76 VkFramebuffer fb_; 77 78 private: 79 enum State { 80 INIT, 81 IDLE, 82 STEP, 83 DRAW, 84 }; 85 86 void update_loop(); 87 thread_loop(Worker * worker)88 static void thread_loop(Worker *worker) { worker->update_loop(); } 89 90 std::thread thread_; 91 std::mutex mutex_; 92 std::condition_variable state_cv_; 93 State state_; 94 }; 95 96 struct Camera { 97 glm::vec3 eye_pos; 98 glm::mat4 view_projection; 99 CameraCamera100 Camera(float eye) : eye_pos(eye) {} 101 }; 102 103 struct FrameData { 104 // signaled when this struct is ready for reuse 105 VkFence fence; 106 107 VkCommandBuffer primary_cmd; 108 std::vector<VkCommandBuffer> worker_cmds; 109 110 VkBuffer buf; 111 uint8_t *base; 112 VkDescriptorSet desc_set; 113 }; 114 115 // called by the constructor 116 void init_workers(); 117 118 bool multithread_; 119 bool use_push_constants_; 120 121 // called mostly by on_key 122 void update_camera(); 123 124 bool sim_paused_; 125 Simulation sim_; 126 Camera camera_; 127 128 std::vector<std::unique_ptr<Worker>> workers_; 129 130 // called by attach_shell 131 void create_render_pass(); 132 void create_shader_modules(); 133 void create_descriptor_set_layout(); 134 void create_pipeline_layout(); 135 void create_pipeline(); 136 137 void create_frame_data(int count); 138 void destroy_frame_data(); 139 void create_fences(); 140 void create_command_buffers(); 141 void create_buffers(); 142 void create_buffer_memory(); 143 void create_descriptor_sets(); 144 145 VkPhysicalDevice physical_dev_; 146 VkDevice dev_; 147 VkQueue queue_; 148 uint32_t queue_family_; 149 VkFormat format_; 150 151 VkPhysicalDeviceProperties physical_dev_props_; 152 std::vector<VkMemoryPropertyFlags> mem_flags_; 153 154 const Meshes *meshes_; 155 156 VkRenderPass render_pass_; 157 VkShaderModule vs_; 158 VkShaderModule fs_; 159 VkDescriptorSetLayout desc_set_layout_; 160 VkPipelineLayout pipeline_layout_; 161 VkPipeline pipeline_; 162 163 VkCommandPool primary_cmd_pool_; 164 std::vector<VkCommandPool> worker_cmd_pools_; 165 VkDescriptorPool desc_pool_; 166 VkDeviceMemory frame_data_mem_; 167 std::vector<FrameData> frame_data_; 168 int frame_data_index_; 169 170 VkClearValue render_pass_clear_value_; 171 VkRenderPassBeginInfo render_pass_begin_info_; 172 173 VkCommandBufferBeginInfo primary_cmd_begin_info_; 174 VkPipelineStageFlags primary_cmd_submit_wait_stages_; 175 VkSubmitInfo primary_cmd_submit_info_; 176 177 // called by attach_swapchain 178 void prepare_viewport(const VkExtent2D &extent); 179 void prepare_framebuffers(VkSwapchainKHR swapchain); 180 181 VkExtent2D extent_; 182 VkViewport viewport_; 183 VkRect2D scissor_; 184 185 std::vector<VkImage> images_; 186 std::vector<VkImageView> image_views_; 187 std::vector<VkFramebuffer> framebuffers_; 188 189 // called by workers 190 void update_simulation(const Worker &worker); 191 void draw_object(const Simulation::Object &obj, FrameData &data, VkCommandBuffer cmd) const; 192 void draw_objects(Worker &worker); 193 }; 194 195 #endif // HOLOGRAM_H 196