/* * Copyright (C) 2016 Google, Inc. * * 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. */ #ifndef SMOKE_H #define SMOKE_H #include <condition_variable> #include <memory> #include <mutex> #include <string> #include <thread> #include <vector> #include <vulkan/vulkan.h> #include <glm/glm.hpp> #include "Simulation.h" #include "Game.h" class Meshes; class Smoke : public Game { public: Smoke(const std::vector<std::string> &args); ~Smoke(); void attach_shell(Shell &sh); void detach_shell(); void attach_swapchain(); void detach_swapchain(); void on_key(Key key); void on_tick(); void on_frame(float frame_pred); private: class Worker { public: Worker(Smoke &smoke, int index, int object_begin, int object_end); void start(); void stop(); void update_simulation(); void draw_objects(VkFramebuffer fb); void wait_idle(); Smoke &smoke_; const int index_; const int object_begin_; const int object_end_; const float tick_interval_; VkFramebuffer fb_; private: enum State { INIT, IDLE, STEP, DRAW, }; void update_loop(); static void thread_loop(Worker *worker) { worker->update_loop(); } std::thread thread_; std::mutex mutex_; std::condition_variable state_cv_; State state_; }; struct Camera { glm::vec3 eye_pos; glm::mat4 view_projection; Camera(float eye) : eye_pos(eye) {} }; struct FrameData { // signaled when this struct is ready for reuse VkFence fence; VkCommandBuffer primary_cmd; std::vector<VkCommandBuffer> worker_cmds; VkBuffer buf; uint8_t *base; VkDescriptorSet desc_set; }; // called by the constructor void init_workers(); bool multithread_; bool use_push_constants_; // called mostly by on_key void update_camera(); bool sim_paused_; Simulation sim_; Camera camera_; std::vector<std::unique_ptr<Worker>> workers_; // called by attach_shell void create_render_pass(); void create_shader_modules(); void create_descriptor_set_layout(); void create_pipeline_layout(); void create_pipeline(); void create_frame_data(int count); void destroy_frame_data(); void create_fences(); void create_command_buffers(); void create_buffers(); void create_buffer_memory(); void create_descriptor_sets(); VkPhysicalDevice physical_dev_; VkDevice dev_; VkQueue queue_; uint32_t queue_family_; VkFormat format_; VkPhysicalDeviceProperties physical_dev_props_; std::vector<VkMemoryPropertyFlags> mem_flags_; const Meshes *meshes_; VkRenderPass render_pass_; VkShaderModule vs_; VkShaderModule fs_; VkDescriptorSetLayout desc_set_layout_; VkPipelineLayout pipeline_layout_; VkPipeline pipeline_; VkCommandPool primary_cmd_pool_; std::vector<VkCommandPool> worker_cmd_pools_; VkDescriptorPool desc_pool_; VkDeviceMemory frame_data_mem_; VkDeviceSize frame_data_aligned_size_; std::vector<FrameData> frame_data_; int frame_data_index_; VkClearValue render_pass_clear_value_; VkRenderPassBeginInfo render_pass_begin_info_; VkCommandBufferBeginInfo primary_cmd_begin_info_; VkPipelineStageFlags primary_cmd_submit_wait_stages_; VkSubmitInfo primary_cmd_submit_info_; // called by attach_swapchain void prepare_viewport(const VkExtent2D &extent); void prepare_framebuffers(VkSwapchainKHR swapchain); VkExtent2D extent_; VkViewport viewport_; VkRect2D scissor_; std::vector<VkImage> images_; std::vector<VkImageView> image_views_; std::vector<VkFramebuffer> framebuffers_; // called by workers void update_simulation(const Worker &worker); void draw_object(const Simulation::Object &obj, FrameData &data, VkCommandBuffer cmd) const; void draw_objects(Worker &worker); }; #endif // HOLOGRAM_H