#ifndef HEADER_GE_VULKAN_DRAW_CALL_HPP #define HEADER_GE_VULKAN_DRAW_CALL_HPP #include #include #include #include #include #include #include #include #include "vulkan_wrapper.h" #include "matrix4.h" #include "vector3d.h" #include "ESceneNodeTypes.h" #include "SColor.h" #include "SMaterial.h" #include "LinearMath/btQuaternion.h" namespace irr { namespace scene { class ISceneNode; class IBillboardSceneNode; struct SParticle; class IMesh; class ILightSceneNode; } } namespace GE { class GECullingTool; class GESPMBuffer; class GEVulkanAnimatedMeshSceneNode; class GEVulkanCameraSceneNode; class GEVulkanDriver; class GEVulkanDynamicBuffer; class GEVulkanDynamicSPMBuffer; class GEVulkanLightHandler; class GEVulkanSkyBoxRenderer; class GEVulkanTextureDescriptor; typedef std::pair, std::vector > VertexDescription; struct ObjectData { float m_translation_x; float m_translation_y; float m_translation_z; float m_hue_change; float m_rotation[4]; float m_scale_x; float m_scale_y; float m_scale_z; irr::video::SColor m_custom_vertex_color; int m_skinning_offset; int m_material_id; float m_texture_trans[2]; // ------------------------------------------------------------------------ void init(irr::scene::ISceneNode* node, int material_id, int skinning_offset, int irrlicht_material_id); // ------------------------------------------------------------------------ void init(irr::scene::IBillboardSceneNode* node, int material_id, const btQuaternion& rotation); // ------------------------------------------------------------------------ void init(const irr::scene::SParticle& particle, int material_id, const btQuaternion& rotation, const irr::core::vector3df& view_position, bool flips, bool sky_particle, bool backface_culling); }; enum GEVulkanPipelineType : unsigned { GVPT_DEPTH = 1, GVPT_SOLID, GVPT_DEFERRED_LIGHTING, GVPT_DEFERRED_CONVERT_COLOR, GVPT_GHOST_DEPTH, GVPT_TRANSPARENT, GVPT_SKYBOX, GVPT_DISPLACE_MASK, GVPT_DISPLACE_COLOR, }; struct GEMaterial; struct PipelineSettings { std::string m_shader_name; std::shared_ptr m_material; char m_drawing_priority; VkPipelineLayout m_custom_pl; VkCompareOp m_depth_op; VkPrimitiveTopology m_topology; VertexDescription m_vertex_description; GEVulkanPipelineType m_pipeline_type; PipelineSettings(); void loadMaterial(const GEMaterial& m); }; struct PipelineData { PipelineSettings m_settings; std::map > m_pipelines; }; struct DrawCallData { VkDrawIndexedIndirectCommand m_cmd; std::string m_shader; std::string m_sorting_key; GESPMBuffer* m_mb; int m_material_id; uint32_t m_dynamic_offset; }; class GEVulkanHiZDepth; class GEVulkanDrawCall { private: typedef std::array TexturesList; const int BILLBOARD_NODE = -1; const int PARTICLE_NODE = -2; std::map m_billboard_buffers; irr::core::vector3df m_view_position; btQuaternion m_billboard_rotation; std::map, std::unordered_map > > > m_visible_nodes; std::map, irr::scene::IMesh*> m_mb_map; std::map > > m_dynamic_spm_buffers; GECullingTool* m_culling_tool; GEVulkanLightHandler* m_light_handler; std::vector m_cmds; std::vector m_visible_objects; GEVulkanDynamicBuffer* m_dynamic_data; GEVulkanDynamicBuffer* m_sbo_data; const VkPhysicalDeviceLimits& m_limits; size_t m_object_data_padded_size; size_t m_skinning_data_padded_size; size_t m_materials_padded_size; size_t m_dynamic_spm_padded_size; bool m_update_data_descriptor_sets; VkDescriptorSetLayout m_data_layout; VkDescriptorPool m_descriptor_pool; std::vector m_data_descriptor_sets; VkPipelineLayout m_pipeline_layout, m_skybox_layout; std::vector m_deferred_layouts; std::unordered_map m_graphics_pipelines; std::unordered_map > m_dyspmb_materials; GEVulkanSkyBoxRenderer* m_skybox_renderer; GEVulkanTextureDescriptor* m_texture_descriptor; std::unordered_set m_skinning_nodes; std::unordered_map > > m_materials_data; GEVulkanHiZDepth* m_hiz_depth; // ------------------------------------------------------------------------ void createAllPipelines(GEVulkanDriver* vk); // ------------------------------------------------------------------------ void createPipeline(GEVulkanDriver* vk, const PipelineSettings& settings, std::unordered_map >& dp_cache); // ------------------------------------------------------------------------ void createVulkanData(); // ------------------------------------------------------------------------ std::string getShader(const irr::video::SMaterial& m); // ------------------------------------------------------------------------ std::string getShader(irr::scene::ISceneNode* node, int material_id); // ------------------------------------------------------------------------ bool bindPipeline(VkCommandBuffer cmd, const std::string& name, VkPipeline* prev_pipeline, GEVulkanPipelineType pt) const; // ------------------------------------------------------------------------ TexturesList getTexturesList(const irr::video::SMaterial& m) { TexturesList textures; for (unsigned i = 0; i < textures.size(); i++) textures[i] = m.TextureLayer[i].Texture; return textures; } // ------------------------------------------------------------------------ size_t getInitialSBOSize() const; // ------------------------------------------------------------------------ void updateDataDescriptorSets(GEVulkanDriver* vk); // ------------------------------------------------------------------------ void bindBaseVertex(GEVulkanDriver* vk, VkCommandBuffer cmd); // ------------------------------------------------------------------------ std::string getDynamicBufferKey(const std::string& shader) const { char drawing_priority = (char)1; auto it = m_graphics_pipelines.find(shader); if (it != m_graphics_pipelines.end()) drawing_priority = it->second.m_settings.m_drawing_priority; return std::string(1, drawing_priority) + shader; } // ------------------------------------------------------------------------ std::string getShaderFromKey(const std::string& key) const { return key.substr(1); } // ------------------------------------------------------------------------ void bindSingleMaterial(VkCommandBuffer cmd, const std::string& cur_pipeline, int material_id, GEVulkanPipelineType pt); // ------------------------------------------------------------------------ void bindDataDescriptor(VkCommandBuffer cmd, int current_buffer_idx, std::vector& dynamic_offsets) { vkCmdBindDescriptorSets(cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, m_pipeline_layout, 1, 1, &m_data_descriptor_sets[current_buffer_idx], dynamic_offsets.size(), dynamic_offsets.data()); } // ------------------------------------------------------------------------ VertexDescription getDefaultVertexDescription() const; // ------------------------------------------------------------------------ size_t getLightDataOffset() const; // ------------------------------------------------------------------------ std::vector getDefaultDynamicOffsets() const; // ------------------------------------------------------------------------ VkRenderPass getRenderPassForPipelineCreation(GEVulkanDriver* vk, GEVulkanPipelineType type); // ------------------------------------------------------------------------ uint32_t getSubpassForPipelineCreation(GEVulkanDriver* vk, GEVulkanPipelineType type); public: // ------------------------------------------------------------------------ GEVulkanDrawCall(); // ------------------------------------------------------------------------ ~GEVulkanDrawCall(); // ------------------------------------------------------------------------ void addNode(irr::scene::ISceneNode* node); // ------------------------------------------------------------------------ void addBillboardNode(irr::scene::ISceneNode* node, irr::scene::ESCENE_NODE_TYPE node_type); // ------------------------------------------------------------------------ void prepare(GEVulkanCameraSceneNode* cam); // ------------------------------------------------------------------------ void generate(GEVulkanDriver* vk); // ------------------------------------------------------------------------ void uploadDynamicData(GEVulkanDriver* vk, GEVulkanCameraSceneNode* cam, VkCommandBuffer custom_cmd = VK_NULL_HANDLE); // ------------------------------------------------------------------------ bool doDepthOnlyRenderingFirst(); // ------------------------------------------------------------------------ void bindAllMaterials(VkCommandBuffer cmd); // ------------------------------------------------------------------------ void prepareRendering(GEVulkanDriver* vk); // ------------------------------------------------------------------------ void prepareViewport(GEVulkanDriver* vk, GEVulkanCameraSceneNode* cam, VkCommandBuffer cmd); // ------------------------------------------------------------------------ void renderPipeline(GEVulkanDriver* vk, VkCommandBuffer cmd, GEVulkanPipelineType pt, bool& rebind_base_vertex); // ------------------------------------------------------------------------ bool renderSkyBox(GEVulkanDriver* vk, VkCommandBuffer cmd); // ------------------------------------------------------------------------ void renderDeferredLighting(GEVulkanDriver* vk, VkCommandBuffer cmd); // ------------------------------------------------------------------------ void renderDeferredConvertColor(GEVulkanDriver* vk, VkCommandBuffer cmd); // ------------------------------------------------------------------------ void renderDisplaceColor(GEVulkanDriver* vk, VkCommandBuffer cmd, VkBool32 has_displace); // ------------------------------------------------------------------------ unsigned getPolyCount() const { unsigned result = 0; for (auto& cmd : m_cmds) result += (cmd.m_cmd.indexCount / 3) * cmd.m_cmd.instanceCount; return result; } // ------------------------------------------------------------------------ void reset() { m_visible_nodes.clear(); m_mb_map.clear(); m_cmds.clear(); m_visible_objects.clear(); m_dyspmb_materials.clear(); m_skinning_nodes.clear(); m_materials_data.clear(); m_dynamic_spm_buffers.clear(); m_skybox_renderer = NULL; } // ------------------------------------------------------------------------ void addSkyBox(irr::scene::ISceneNode* node); // ------------------------------------------------------------------------ void addLightNode(irr::scene::ILightSceneNode* node); // ------------------------------------------------------------------------ bool hasShaderForRendering(const std::string& shader) { const std::string& dbk = getDynamicBufferKey(shader); if (m_dynamic_spm_buffers.find(dbk) != m_dynamic_spm_buffers.end()) return true; return m_materials_data.find(shader) != m_materials_data.end(); } // ------------------------------------------------------------------------ GEVulkanHiZDepth* getHiZDepth() const { return m_hiz_depth; } }; // GEVulkanDrawCall } #endif