diff --git a/src/graphics/command_buffer.cpp b/src/graphics/command_buffer.cpp new file mode 100644 index 000000000..edf92d5b7 --- /dev/null +++ b/src/graphics/command_buffer.cpp @@ -0,0 +1,358 @@ +// SuperTuxKart - a fun racing game with go-kart +// Copyright (C) 2015 SuperTuxKart-Team +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 3 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +#include "graphics/command_buffer.hpp" +#include "graphics/central_settings.hpp" + + template<> + void InstanceFiller::add(GLMesh *mesh, scene::ISceneNode *node, InstanceDataSingleTex &instance) + { + fillOriginOrientationScale(node, instance); + instance.Texture = mesh->TextureHandles[0]; + } + + template<> + void InstanceFiller::add(GLMesh *mesh, scene::ISceneNode *node, InstanceDataDualTex &instance) + { + fillOriginOrientationScale(node, instance); + instance.Texture = mesh->TextureHandles[0]; + instance.SecondTexture = mesh->TextureHandles[1]; + } + + template<> + void InstanceFiller::add(GLMesh *mesh, scene::ISceneNode *node, InstanceDataThreeTex &instance) + { + fillOriginOrientationScale(node, instance); + instance.Texture = mesh->TextureHandles[0]; + instance.SecondTexture = mesh->TextureHandles[1]; + instance.ThirdTexture = mesh->TextureHandles[2]; + } + + template<> + void InstanceFiller::add(GLMesh *mesh, scene::ISceneNode *node, GlowInstanceData &instance) + { + fillOriginOrientationScale(node, instance); + STKMeshSceneNode *nd = dynamic_cast(node); + instance.Color = nd->getGlowColor().color; + } + + +CommandBuffer::CommandBuffer(): +m_offset(NULL), m_size(NULL), m_poly_count(0) +{ + glGenBuffers(1, &m_draw_indirect_cmd_id); + glBindBuffer(GL_DRAW_INDIRECT_BUFFER, m_draw_indirect_cmd_id); + if (CVS->supportsAsyncInstanceUpload()) + { + glBufferStorage(GL_DRAW_INDIRECT_BUFFER, + 10000 * sizeof(DrawElementsIndirectCommand), + 0, GL_MAP_PERSISTENT_BIT | GL_MAP_WRITE_BIT); + m_draw_indirect_cmd = (DrawElementsIndirectCommand *) + glMapBufferRange(GL_DRAW_INDIRECT_BUFFER, + 0, 10000 * sizeof(DrawElementsIndirectCommand), + GL_MAP_PERSISTENT_BIT | GL_MAP_WRITE_BIT); + } + else + { + glBufferData(GL_DRAW_INDIRECT_BUFFER, + 10000 * sizeof(DrawElementsIndirectCommand), + 0, GL_STREAM_DRAW); + } +} + +CommandBuffer::~CommandBuffer() +{ + glDeleteBuffers(1, &m_draw_indirect_cmd_id); + delete[] m_offset; + delete[] m_size; +} + + +template +void CommandBuffer::fillMaterial(int material_id, + MeshMap *mesh_map, + std::vector &instanced_list, + T *instance_buffer) +{ + m_offset[material_id] = m_instance_buffer_offset; + FillInstances(mesh_map[material_id], + instanced_list, + instance_buffer, + m_draw_indirect_cmd, + m_instance_buffer_offset, + m_command_buffer_offset, + m_poly_count); + + m_size[material_id] = m_command_buffer_offset - m_instance_buffer_offset; +} + +SolidCommandBuffer::SolidCommandBuffer(): CommandBuffer() +{ + m_offset = new size_t[static_cast(Material::SHADERTYPE_COUNT)]; + m_size = new size_t[static_cast(Material::SHADERTYPE_COUNT)]; +} + +void SolidCommandBuffer::fill(MeshMap *mesh_map, std::vector instanced_lists[]) +{ + m_instance_buffer_offset = 0; + m_command_buffer_offset = 0; + m_poly_count = 0; + + //Dual textures materials + InstanceDataDualTex *instance_buffer_dual_tex; + + if (CVS->supportsAsyncInstanceUpload()) + { + instance_buffer_dual_tex = + (InstanceDataDualTex*)VAOManager::getInstance()->getInstanceBufferPtr(InstanceTypeDualTex); + } + else + { + glBindBuffer(GL_ARRAY_BUFFER, VAOManager::getInstance()->getInstanceBuffer(InstanceTypeDualTex)); + instance_buffer_dual_tex = + (InstanceDataDualTex*) glMapBufferRange(GL_ARRAY_BUFFER, 0, + 10000 * sizeof(InstanceDataDualTex), + GL_MAP_WRITE_BIT | GL_MAP_UNSYNCHRONIZED_BIT | GL_MAP_INVALIDATE_BUFFER_BIT); + glBindBuffer(GL_DRAW_INDIRECT_BUFFER, m_draw_indirect_cmd_id); + + + m_draw_indirect_cmd = + (DrawElementsIndirectCommand*)glMapBufferRange(GL_DRAW_INDIRECT_BUFFER, 0, + 10000 * sizeof(DrawElementsIndirectCommand), + GL_MAP_WRITE_BIT | GL_MAP_UNSYNCHRONIZED_BIT | GL_MAP_INVALIDATE_BUFFER_BIT); + } + + Material::ShaderType dual_tex_materials[5] = + { + Material::SHADERTYPE_SOLID, + Material::SHADERTYPE_ALPHA_TEST, + Material::SHADERTYPE_SOLID_UNLIT, + Material::SHADERTYPE_SPHERE_MAP, + Material::SHADERTYPE_VEGETATION + }; + + int material_id; + for(int i=0;i<5;i++) + { + material_id = static_cast(dual_tex_materials[i]); + fillMaterial( material_id, + mesh_map, + instanced_lists[material_id], + instance_buffer_dual_tex); + } + + + //Three textures materials + InstanceDataThreeTex *instance_buffer_three_tex; + + if (!CVS->supportsAsyncInstanceUpload()) + { + glUnmapBuffer(GL_ARRAY_BUFFER); + glBindBuffer(GL_ARRAY_BUFFER, VAOManager::getInstance()->getInstanceBuffer(InstanceTypeThreeTex)); + instance_buffer_three_tex = (InstanceDataThreeTex*) + glMapBufferRange(GL_ARRAY_BUFFER, 0, + 10000 * sizeof(InstanceDataSingleTex), + GL_MAP_WRITE_BIT | GL_MAP_UNSYNCHRONIZED_BIT | GL_MAP_INVALIDATE_BUFFER_BIT); + } + + Material::ShaderType three_tex_materials[2] = + { + Material::SHADERTYPE_DETAIL_MAP, + Material::SHADERTYPE_NORMAL_MAP + }; + for(int i=0;i<2;i++) + { + material_id = static_cast(three_tex_materials[i]); + fillMaterial( material_id, + mesh_map, + instanced_lists[material_id], + instance_buffer_three_tex); + } + + if (!CVS->supportsAsyncInstanceUpload()) + { + glUnmapBuffer(GL_ARRAY_BUFFER); + glUnmapBuffer(GL_DRAW_INDIRECT_BUFFER); + } +} //SolidCommandBuffer::fill + +ShadowCommandBuffer::ShadowCommandBuffer(): CommandBuffer() +{ + m_offset = new size_t[4 * static_cast(Material::SHADERTYPE_COUNT)]; + m_size = new size_t[4 * static_cast(Material::SHADERTYPE_COUNT)]; +} + +void ShadowCommandBuffer::fill(MeshMap *mesh_map, std::vector instanced_lists[]) +{ + m_instance_buffer_offset = 0; + m_command_buffer_offset = 0; + m_poly_count = 0; + InstanceDataSingleTex *shadow_instance_buffer; + + if (CVS->supportsAsyncInstanceUpload()) + { + shadow_instance_buffer = (InstanceDataSingleTex*)VAOManager::getInstance()->getInstanceBufferPtr(InstanceTypeShadow); + } + else + { + glBindBuffer(GL_ARRAY_BUFFER, VAOManager::getInstance()->getInstanceBuffer(InstanceTypeShadow)); + shadow_instance_buffer = + (InstanceDataSingleTex*) glMapBufferRange(GL_ARRAY_BUFFER, 0, + 10000 * sizeof(InstanceDataDualTex), + GL_MAP_WRITE_BIT | GL_MAP_UNSYNCHRONIZED_BIT | GL_MAP_INVALIDATE_BUFFER_BIT); + glBindBuffer(GL_DRAW_INDIRECT_BUFFER, m_draw_indirect_cmd_id); + m_draw_indirect_cmd = + (DrawElementsIndirectCommand*) glMapBufferRange(GL_DRAW_INDIRECT_BUFFER, 0, + 10000 * sizeof(DrawElementsIndirectCommand), + GL_MAP_WRITE_BIT | GL_MAP_UNSYNCHRONIZED_BIT | GL_MAP_INVALIDATE_BUFFER_BIT); + } + + Material::ShaderType materials[7] = + { + Material::SHADERTYPE_SOLID, + Material::SHADERTYPE_ALPHA_TEST, + Material::SHADERTYPE_SOLID_UNLIT, + Material::SHADERTYPE_NORMAL_MAP, + Material::SHADERTYPE_SPHERE_MAP, + Material::SHADERTYPE_DETAIL_MAP, + Material::SHADERTYPE_VEGETATION + }; + int material_id; + + for(int cascade=0;cascade<4;cascade++) + { + for(int i=0;i<7;i++) + { + material_id = cascade * 7 + static_cast(materials[i]); + fillMaterial( material_id, + mesh_map, + instanced_lists[material_id], + shadow_instance_buffer); + } + } + + if (!CVS->supportsAsyncInstanceUpload()) + { + glUnmapBuffer(GL_ARRAY_BUFFER); + glUnmapBuffer(GL_DRAW_INDIRECT_BUFFER); + } + +} //ShadowCommandBuffer::fill + +ReflectiveShadowMapCommandBuffer::ReflectiveShadowMapCommandBuffer(): CommandBuffer() +{ + m_offset = new size_t[static_cast(Material::SHADERTYPE_COUNT)]; + m_size = new size_t[static_cast(Material::SHADERTYPE_COUNT)]; +} + + +void ReflectiveShadowMapCommandBuffer::fill(MeshMap *mesh_map, std::vector instanced_lists[]) +{ + m_instance_buffer_offset = 0; + m_command_buffer_offset = 0; + m_poly_count = 0; + InstanceDataSingleTex *rsm_instance_buffer; + + if (CVS->supportsAsyncInstanceUpload()) + { + rsm_instance_buffer = (InstanceDataSingleTex*)VAOManager::getInstance()->getInstanceBufferPtr(InstanceTypeShadow); + } + else + { + glBindBuffer(GL_ARRAY_BUFFER, + VAOManager::getInstance()->getInstanceBuffer(InstanceTypeRSM)); + rsm_instance_buffer = + (InstanceDataSingleTex*)glMapBufferRange(GL_ARRAY_BUFFER, 0, + 10000 * sizeof(InstanceDataDualTex), + GL_MAP_WRITE_BIT | GL_MAP_UNSYNCHRONIZED_BIT | GL_MAP_INVALIDATE_BUFFER_BIT); + glBindBuffer(GL_DRAW_INDIRECT_BUFFER, m_draw_indirect_cmd_id); + m_draw_indirect_cmd = + (DrawElementsIndirectCommand*)glMapBufferRange(GL_DRAW_INDIRECT_BUFFER, 0, + 10000 * sizeof(DrawElementsIndirectCommand), + GL_MAP_WRITE_BIT | GL_MAP_UNSYNCHRONIZED_BIT | GL_MAP_INVALIDATE_BUFFER_BIT); + } + + Material::ShaderType materials[5] = + { + Material::SHADERTYPE_SOLID, + Material::SHADERTYPE_ALPHA_TEST, + Material::SHADERTYPE_SOLID_UNLIT, + Material::SHADERTYPE_DETAIL_MAP, + Material::SHADERTYPE_NORMAL_MAP, + }; + int material_id; + + for(int i=0;i<5;i++) + { + material_id = static_cast(materials[i]); + fillMaterial( material_id, + mesh_map, + instanced_lists[material_id], + rsm_instance_buffer); + } + + if (!CVS->supportsAsyncInstanceUpload()) + { + glUnmapBuffer(GL_ARRAY_BUFFER); + glUnmapBuffer(GL_DRAW_INDIRECT_BUFFER); + } + +} //ReflectiveShadowMapCommandBuffer::fill + +GlowCommandBuffer::GlowCommandBuffer() +{ + m_offset = new size_t[1]; + m_size = new size_t[1]; +} + +void GlowCommandBuffer::fill(MeshMap *mesh_map, std::vector instanced_lists[]) +{ + m_instance_buffer_offset = 0; + m_command_buffer_offset = 0; + m_poly_count = 0; + GlowInstanceData *glow_instance_buffer; + + if (CVS->supportsAsyncInstanceUpload()) + { + glow_instance_buffer = (GlowInstanceData*)VAOManager::getInstance()->getInstanceBufferPtr(InstanceTypeGlow); + } + else + { + glBindBuffer(GL_ARRAY_BUFFER, + VAOManager::getInstance()->getInstanceBuffer(InstanceTypeGlow)); + glow_instance_buffer = + (GlowInstanceData*)glMapBufferRange(GL_ARRAY_BUFFER, 0, + 10000 * sizeof(InstanceDataDualTex), + GL_MAP_WRITE_BIT | GL_MAP_UNSYNCHRONIZED_BIT | GL_MAP_INVALIDATE_BUFFER_BIT); + glBindBuffer(GL_DRAW_INDIRECT_BUFFER, m_draw_indirect_cmd_id); + m_draw_indirect_cmd = + (DrawElementsIndirectCommand*)glMapBufferRange(GL_DRAW_INDIRECT_BUFFER, 0, + 10000 * sizeof(DrawElementsIndirectCommand), + GL_MAP_WRITE_BIT | GL_MAP_UNSYNCHRONIZED_BIT | GL_MAP_INVALIDATE_BUFFER_BIT); + } + + fillMaterial( 0, + mesh_map, + instanced_lists[0], + glow_instance_buffer); + + if (!CVS->supportsAsyncInstanceUpload()) + { + glUnmapBuffer(GL_ARRAY_BUFFER); + glUnmapBuffer(GL_DRAW_INDIRECT_BUFFER); + } +} //GlowCommandBuffer::fill diff --git a/src/graphics/command_buffer.hpp b/src/graphics/command_buffer.hpp new file mode 100644 index 000000000..28a81f17e --- /dev/null +++ b/src/graphics/command_buffer.hpp @@ -0,0 +1,188 @@ +// SuperTuxKart - a fun racing game with go-kart +// Copyright (C) 2015 SuperTuxKart-Team +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 3 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +#ifndef HEADER_COMMAND_BUFFER_HPP +#define HEADER_COMMAND_BUFFER_HPP + +#include "graphics/gl_headers.hpp" +#include "graphics/material.hpp" + +#include "graphics/stk_mesh_scene_node.hpp" +#include "graphics/vao_manager.hpp" +#include +#include + + +typedef std::vector > InstanceList; +typedef std::unordered_map MeshMap; + + +template +void fillOriginOrientationScale(scene::ISceneNode *node, InstanceData &instance) +{ + const core::matrix4 &mat = node->getAbsoluteTransformation(); + const core::vector3df &Origin = mat.getTranslation(); + const core::vector3df &Orientation = mat.getRotationDegrees(); + const core::vector3df &Scale = mat.getScale(); + instance.Origin.X = Origin.X; + instance.Origin.Y = Origin.Y; + instance.Origin.Z = Origin.Z; + instance.Orientation.X = Orientation.X; + instance.Orientation.Y = Orientation.Y; + instance.Orientation.Z = Orientation.Z; + instance.Scale.X = Scale.X; + instance.Scale.Y = Scale.Y; + instance.Scale.Z = Scale.Z; +} + +template +struct InstanceFiller +{ + static void add(GLMesh *, scene::ISceneNode *, InstanceData &); +}; + +template +void FillInstances_impl(InstanceList instance_list, + T * instance_buffer, + DrawElementsIndirectCommand *command_buffer, + size_t &instance_buffer_offset, + size_t &command_buffer_offset, + size_t &poly_count) +{ + // Should never be empty + GLMesh *mesh = instance_list.front().first; + size_t initial_offset = instance_buffer_offset; + + for (unsigned i = 0; i < instance_list.size(); i++) + { + auto &Tp = instance_list[i]; + scene::ISceneNode *node = Tp.second; + InstanceFiller::add(mesh, node, instance_buffer[instance_buffer_offset++]); + assert(instance_buffer_offset * sizeof(T) < 10000 * sizeof(InstanceDataDualTex)); //TODO + } + + DrawElementsIndirectCommand &CurrentCommand = command_buffer[command_buffer_offset++]; + CurrentCommand.baseVertex = mesh->vaoBaseVertex; + CurrentCommand.count = mesh->IndexCount; + CurrentCommand.firstIndex = mesh->vaoOffset / 2; + CurrentCommand.baseInstance = initial_offset; + CurrentCommand.instanceCount = instance_buffer_offset - initial_offset; + + poly_count += (instance_buffer_offset - initial_offset) * mesh->IndexCount / 3; +} + +template +void FillInstances( const MeshMap &gathered_GL_mesh, + std::vector &instanced_list, + T *instance_buffer, + DrawElementsIndirectCommand *command_buffer, + size_t &instance_buffer_offset, + size_t &command_buffer_offset, + size_t &poly_count) +{ + auto It = gathered_GL_mesh.begin(), E = gathered_GL_mesh.end(); + for (; It != E; ++It) + { + FillInstances_impl(It->second, instance_buffer, command_buffer, instance_buffer_offset, command_buffer_offset, poly_count); + if (!CVS->isAZDOEnabled()) + instanced_list.push_back(It->second.front().first); + } +} + + +class CommandBuffer +{ +protected: + GLuint m_draw_indirect_cmd_id; + DrawElementsIndirectCommand *m_draw_indirect_cmd; + size_t *m_offset; + size_t *m_size; + size_t m_poly_count; + size_t m_instance_buffer_offset; + size_t m_command_buffer_offset; + + template + void fillMaterial(int material_id, + MeshMap *mesh_map, + std::vector &instanced_list, + T *instance_buffer); + +public: + CommandBuffer(); + virtual ~CommandBuffer(); + + inline size_t getPolyCount() {return m_poly_count;} + + inline void bind() + { + glBindBuffer(GL_DRAW_INDIRECT_BUFFER, m_draw_indirect_cmd_id); + } + + /** Draw the i-th mesh with the specified material + * (require GL_ARB_base_instance and GL_ARB_draw_indirect extensions) + * \param shader_type Only render meshes with the specified material + */ + inline void drawIndirect(Material::ShaderType shader_type, int i) + { + glDrawElementsIndirect(GL_TRIANGLES, + GL_UNSIGNED_SHORT, + (const void*)(m_offset[static_cast(shader_type) + i] * sizeof(DrawElementsIndirectCommand))); + } + + /** Draw the meshes with the specified material + * (require AZDO extensions) + * \param shader_type Only render meshes with the specified material + */ + inline void multidrawIndirect(Material::ShaderType shader_type) + { + glMultiDrawElementsIndirect(GL_TRIANGLES, + GL_UNSIGNED_SHORT, + (const void*)(m_offset[static_cast(shader_type)] * sizeof(DrawElementsIndirectCommand)), + (int) m_size[static_cast(shader_type)], + sizeof(DrawElementsIndirectCommand)); + } +}; + +class SolidCommandBuffer: public CommandBuffer +{ +public: + SolidCommandBuffer(); + void fill(MeshMap *mesh_map, std::vector instanced_lists[]); +}; + +class ShadowCommandBuffer: public CommandBuffer +{ +public: + ShadowCommandBuffer(); + void fill(MeshMap *mesh_map, std::vector instanced_lists[]); +}; + +class ReflectiveShadowMapCommandBuffer: public CommandBuffer +{ +public: + ReflectiveShadowMapCommandBuffer(); + void fill(MeshMap *mesh_map, std::vector instanced_lists[]); +}; + +class GlowCommandBuffer: public CommandBuffer +{ +public: + GlowCommandBuffer(); + void fill(MeshMap *mesh_map, std::vector instanced_lists[]); +}; + +#endif //HEADER_COMMAND_BUFFER_HPP diff --git a/src/graphics/draw_calls.cpp b/src/graphics/draw_calls.cpp index be19cb511..17cdae8dd 100644 --- a/src/graphics/draw_calls.cpp +++ b/src/graphics/draw_calls.cpp @@ -28,63 +28,6 @@ using namespace irr; namespace { - template - void fillOriginOrientationScale(scene::ISceneNode *node, InstanceData &instance) - { - const core::matrix4 &mat = node->getAbsoluteTransformation(); - const core::vector3df &Origin = mat.getTranslation(); - const core::vector3df &Orientation = mat.getRotationDegrees(); - const core::vector3df &Scale = mat.getScale(); - instance.Origin.X = Origin.X; - instance.Origin.Y = Origin.Y; - instance.Origin.Z = Origin.Z; - instance.Orientation.X = Orientation.X; - instance.Orientation.Y = Orientation.Y; - instance.Orientation.Z = Orientation.Z; - instance.Scale.X = Scale.X; - instance.Scale.Y = Scale.Y; - instance.Scale.Z = Scale.Z; - } - - template - struct InstanceFiller - { - static void add(GLMesh *, scene::ISceneNode *, InstanceData &); - }; - - template<> - void InstanceFiller::add(GLMesh *mesh, scene::ISceneNode *node, InstanceDataSingleTex &Instance) - { - fillOriginOrientationScale(node, Instance); - Instance.Texture = mesh->TextureHandles[0]; - } - - template<> - void InstanceFiller::add(GLMesh *mesh, scene::ISceneNode *node, InstanceDataDualTex &Instance) - { - fillOriginOrientationScale(node, Instance); - Instance.Texture = mesh->TextureHandles[0]; - Instance.SecondTexture = mesh->TextureHandles[1]; - } - - template<> - void InstanceFiller::add(GLMesh *mesh, scene::ISceneNode *node, InstanceDataThreeTex &Instance) - { - fillOriginOrientationScale(node, Instance); - Instance.Texture = mesh->TextureHandles[0]; - Instance.SecondTexture = mesh->TextureHandles[1]; - Instance.ThirdTexture = mesh->TextureHandles[2]; - } - - template<> - void InstanceFiller::add(GLMesh *mesh, scene::ISceneNode *node, GlowInstanceData &Instance) - { - fillOriginOrientationScale(node, Instance); - STKMeshSceneNode *nd = dynamic_cast(node); - Instance.Color = nd->getGlowColor().color; - } - - void FixBoundingBoxes(scene::ISceneNode* node) { for (scene::ISceneNode *child : node->getChildren()) @@ -94,58 +37,7 @@ namespace } } - - template - void FillInstances_impl(DrawCalls::InstanceList instance_list, - T * InstanceBuffer, - DrawElementsIndirectCommand *CommandBuffer, - size_t &InstanceBufferOffset, - size_t &CommandBufferOffset, - size_t &PolyCount) - { - // Should never be empty - GLMesh *mesh = instance_list.front().first; - size_t InitialOffset = InstanceBufferOffset; - for (unsigned i = 0; i < instance_list.size(); i++) - { - auto &Tp = instance_list[i]; - scene::ISceneNode *node = Tp.second; - InstanceFiller::add(mesh, node, InstanceBuffer[InstanceBufferOffset++]); - assert(InstanceBufferOffset * sizeof(T) < 10000 * sizeof(InstanceDataDualTex)); - } - - DrawElementsIndirectCommand &CurrentCommand = CommandBuffer[CommandBufferOffset++]; - CurrentCommand.baseVertex = mesh->vaoBaseVertex; - CurrentCommand.count = mesh->IndexCount; - CurrentCommand.firstIndex = mesh->vaoOffset / 2; - CurrentCommand.baseInstance = InitialOffset; - CurrentCommand.instanceCount = InstanceBufferOffset - InitialOffset; - - PolyCount += (InstanceBufferOffset - InitialOffset) * mesh->IndexCount / 3; - } - - template - void FillInstances( const DrawCalls::MeshMap &GatheredGLMesh, - std::vector &InstancedList, - T *InstanceBuffer, - DrawElementsIndirectCommand *CommandBuffer, - size_t &InstanceBufferOffset, - size_t &CommandBufferOffset, - size_t &Polycount) - { - auto It = GatheredGLMesh.begin(), E = GatheredGLMesh.end(); - for (; It != E; ++It) - { - FillInstances_impl(It->second, InstanceBuffer, CommandBuffer, InstanceBufferOffset, CommandBufferOffset, Polycount); - if (!CVS->isAZDOEnabled()) - InstancedList.push_back(It->second.front().first); - } - } - - - - } //namespace @@ -653,6 +545,21 @@ void DrawCalls::prepareDrawCalls( ShadowMatrices& shadow_matrices, scene::ICamer { #pragma omp section { + + //TODO + /*std::vector instanced_lists[Material::SHADERTYPE_COUNT]; + instanced_lists[static_cast(Material::SHADERTYPE_SOLID)] = ListInstancedMatDefault::getInstance()->SolidPass; + instanced_lists[static_cast(Material::SHADERTYPE_ALPHA_TEST)] = ListInstancedMatAlphaRef::getInstance()->SolidPass; + instanced_lists[static_cast(Material::SHADERTYPE_SOLID_UNLIT)] = ListInstancedMatUnlit::getInstance()->SolidPass; + instanced_lists[static_cast(Material::SHADERTYPE_SPHERE_MAP)] = ListInstancedMatSphereMap::getInstance()->SolidPass; + instanced_lists[static_cast(Material::SHADERTYPE_VEGETATION)] = ListInstancedMatGrass::getInstance()->SolidPass; + instanced_lists[static_cast(Material::SHADERTYPE_DETAIL_MAP)] = ListInstancedMatDetails::getInstance()->SolidPass; + instanced_lists[static_cast(Material::SHADERTYPE_NORMAL_MAP)] = ListInstancedMatNormalMap::getInstance()->SolidPass; + + m_solid_cmd_buffer.fill(m_solid_pass_mesh, instanced_lists);*/ + + + size_t offset = 0, current_cmd = 0; if (!CVS->supportsAsyncInstanceUpload()) { @@ -661,28 +568,6 @@ void DrawCalls::prepareDrawCalls( ShadowMatrices& shadow_matrices, scene::ICamer glBindBuffer(GL_DRAW_INDIRECT_BUFFER, SolidPassCmd::getInstance()->drawindirectcmd); CmdBuffer = (DrawElementsIndirectCommand*)glMapBufferRange(GL_DRAW_INDIRECT_BUFFER, 0, 10000 * sizeof(DrawElementsIndirectCommand), GL_MAP_WRITE_BIT | GL_MAP_UNSYNCHRONIZED_BIT | GL_MAP_INVALIDATE_BUFFER_BIT); } - - - //TODO: replace duplicated code with a loop - /* - Material::ShaderType dual_tex_materials[5] = {Material::SHADERTYPE_SOLID, - Material::SHADERTYPE_ALPHA_TEST, - Material::SHADERTYPE_SOLID_UNLIT, - Material::SHADERTYPE_SPHERE_MAP, - Material::SHADERTYPE_VEGETATION}; - - for(int i=0;i<1;i++) - { - SolidPassCmd::getInstance()->Offset[dual_tex_materials[i]] = current_cmd; - FillInstances(m_solid_pass_mesh[dual_tex_materials[i]], - ListInstancedMatDefault::getInstance()->SolidPass, //we need to change this line to something more generic - InstanceBufferDualTex, - CmdBuffer, - offset, - current_cmd, - SolidPoly); - SolidPassCmd::getInstance()->Size[dual_tex_materials[i]] = current_cmd - SolidPassCmd::getInstance()->Offset[dual_tex_materials[i]]; - }*/ // Default Material diff --git a/src/graphics/draw_calls.hpp b/src/graphics/draw_calls.hpp index 12015950c..6c9a7ca37 100644 --- a/src/graphics/draw_calls.hpp +++ b/src/graphics/draw_calls.hpp @@ -18,18 +18,21 @@ #ifndef HEADER_DRAW_CALLS_HPP #define HEADER_DRAW_CALLS_HPP +#include "graphics/command_buffer.hpp" +#include "graphics/draw_tools.hpp" #include "graphics/gpu_particles.hpp" #include "graphics/shadow_matrices.hpp" #include "graphics/stk_billboard.hpp" #include "graphics/stk_mesh.hpp" #include + #include + class DrawCalls { public: - typedef std::vector > InstanceList; - typedef std::unordered_map MeshMap; + GLsync m_sync = 0; //TODO: make it private. Should it be in shader_based_renderer? @@ -41,6 +44,12 @@ private: std::vector m_billboard_list; std::vector m_particles_list; + SolidCommandBuffer m_solid_cmd_buffer; + ShadowCommandBuffer m_shadow_cmd_buffer; + ReflectiveShadowMapCommandBuffer m_reflective_shadow_map_cmd_buffer; + GlowCommandBuffer m_glow_cmd_buffer; + + irr::core::vector3df windDir; //TODO: same member in geometry_passes MeshMap m_solid_pass_mesh [Material::SHADERTYPE_COUNT] ; diff --git a/src/graphics/draw_tools.hpp b/src/graphics/draw_tools.hpp index 087996de7..b994eded2 100644 --- a/src/graphics/draw_tools.hpp +++ b/src/graphics/draw_tools.hpp @@ -21,6 +21,7 @@ #include "graphics/shader.hpp" #include "graphics/irr_driver.hpp" #include "graphics/stk_mesh.hpp" +#include "graphics/texture_manager.hpp" // ---------------------------------------------------------------------------- diff --git a/src/graphics/material_type.cpp b/src/graphics/material_type.cpp new file mode 100644 index 000000000..676eac172 --- /dev/null +++ b/src/graphics/material_type.cpp @@ -0,0 +1,19 @@ +// SuperTuxKart - a fun racing game with go-kart +// Copyright (C) 2015 SuperTuxKart-Team +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 3 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +#include "graphics/material_type.hpp" + diff --git a/src/graphics/material_type.hpp b/src/graphics/material_type.hpp new file mode 100644 index 000000000..d3f57a08a --- /dev/null +++ b/src/graphics/material_type.hpp @@ -0,0 +1,66 @@ +// SuperTuxKart - a fun racing game with go-kart +// Copyright (C) 2015 SuperTuxKart-Team +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 3 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +#ifndef HEADER_MATERIAL_TYPE_HPP +#define HEADER_MATERIAL_TYPE_HPP + +#include "graphics/shader.hpp" + +/* +struct MaterialType +{ + Shader *m_first_pass_shader; + Shader *m_second_pass_shader; + Shader *m_shadow_shader; + Shader *m_reflective_shadow_map_shader; + + Material::ShaderType m_shader_type; +};*/ + +/* +// ============================================================================ +struct DefaultMaterial +{ + typedef InstancedObjectPass1Shader InstancedFirstPassShader; + typedef InstancedObjectPass2Shader InstancedSecondPassShader; + typedef InstancedShadowShader InstancedShadowPassShader; + typedef CInstancedRSMShader InstancedRSMShader; + typedef ListInstancedMatDefault InstancedList; + typedef Shaders::ObjectPass1Shader FirstPassShader; + typedef Shaders::ObjectPass2Shader SecondPassShader; + typedef ShadowShader ShadowPassShader; + typedef CRSMShader RSMShader; + typedef ListMatDefault List; + static const enum video::E_VERTEX_TYPE VertexType = video::EVT_STANDARD; + static const enum Material::ShaderType MaterialType + = Material::SHADERTYPE_SOLID; + static const enum InstanceType Instance = InstanceTypeDualTex; + static const STK::Tuple FirstPassTextures; + static const STK::Tuple SecondPassTextures; + static const STK::Tuple<> ShadowTextures; + static const STK::Tuple RSMTextures; +}; // struct DefaultMaterial + +const STK::Tuple DefaultMaterial::FirstPassTextures + = STK::Tuple(1); +const STK::Tuple DefaultMaterial::SecondPassTextures + = STK::Tuple(0, 1); +const STK::Tuple<> DefaultMaterial::ShadowTextures; +const STK::Tuple DefaultMaterial::RSMTextures = STK::Tuple(0); +*/ + +#endif //HEADER_MATERIAL_TYPE_HPP diff --git a/src/graphics/shader_based_renderer.cpp b/src/graphics/shader_based_renderer.cpp index 6d3e44b54..89ddc0608 100644 --- a/src/graphics/shader_based_renderer.cpp +++ b/src/graphics/shader_based_renderer.cpp @@ -491,17 +491,17 @@ void ShaderBasedRenderer::renderPostProcessing(Camera * const camera) ShaderBasedRenderer::ShaderBasedRenderer() { - if (CVS->isAZDOEnabled()) + /*if (CVS->isAZDOEnabled()) m_solid_first_pass = new AZDOSolidFirstPass(); else if (CVS->supportsIndirectInstancingRendering()) m_solid_first_pass = new IndirectInstancedSolidFirstPass(); else - m_solid_first_pass = new GL3SolidFirstPass(); + m_solid_first_pass = new GL3SolidFirstPass();*/ } ShaderBasedRenderer::~ShaderBasedRenderer() { - delete m_solid_first_pass; + //delete m_solid_first_pass; } void ShaderBasedRenderer::addSunLight(const core::vector3df &pos) { diff --git a/src/graphics/shader_based_renderer.hpp b/src/graphics/shader_based_renderer.hpp index 0624e05e2..2dd25588e 100644 --- a/src/graphics/shader_based_renderer.hpp +++ b/src/graphics/shader_based_renderer.hpp @@ -37,7 +37,7 @@ private: ShadowMatrices m_shadow_matrices; irr::core::vector3df m_wind_dir; - SolidFirstPass *m_solid_first_pass; + //SolidFirstPass *m_solid_first_pass; void compressPowerUpTextures(); void setOverrideMaterial(); diff --git a/src/graphics/solid_first_pass.cpp b/src/graphics/solid_first_pass.cpp index 6e4c7b0f7..0c8e70b3f 100644 --- a/src/graphics/solid_first_pass.cpp +++ b/src/graphics/solid_first_pass.cpp @@ -15,6 +15,8 @@ // along with this program; if not, write to the Free Software // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +/* #include "graphics/solid_first_pass.hpp" #include "graphics/glwrap.hpp" #include "graphics/irr_driver.hpp" @@ -55,6 +57,7 @@ void AZDOSolidFirstPass::render(const DrawCalls& draw_calls, irr::core::vector3d draw_calls.renderImmediateDrawList(); - + } +*/ diff --git a/src/graphics/solid_first_pass.hpp b/src/graphics/solid_first_pass.hpp index 190b097bb..492734590 100644 --- a/src/graphics/solid_first_pass.hpp +++ b/src/graphics/solid_first_pass.hpp @@ -29,24 +29,24 @@ public: }; /** This class only uses OpenGL3.x functions */ -class GL3SolidFirstPass: public SolidFirstPass +/*class GL3SolidFirstPass: public SolidFirstPass { void render(const DrawCalls& draw_calls, irr::core::vector3df wind_dir); -}; +};*/ /** Require GL_ARB_base_instance and GL_ARB_draw_indirect extensions */ -class IndirectInstancedSolidFirstPass: public SolidFirstPass +/*class IndirectInstancedSolidFirstPass: public SolidFirstPass { void render(const DrawCalls& draw_calls, irr::core::vector3df wind_dir); -}; +};*/ /** AZDO: Approaching Zero Driver Overhead * Require GL_ARB_base_instance, GL_ARB_draw_indirect, * GL_ARB_bindless_texture and GL_ARB_multi_draw_indirect extensions */ -class AZDOSolidFirstPass: public SolidFirstPass +/*class AZDOSolidFirstPass: public SolidFirstPass { void render(const DrawCalls& draw_calls, irr::core::vector3df wind_dir); -}; +};*/ #endif //HEADER_SOLID_FIRST_PASS_HPP diff --git a/src/graphics/stk_scene_manager.hpp b/src/graphics/stk_scene_manager.hpp index 2509da993..235372120 100644 --- a/src/graphics/stk_scene_manager.hpp +++ b/src/graphics/stk_scene_manager.hpp @@ -30,7 +30,7 @@ #include "utils/singleton.hpp" template -class CommandBuffer : public Singleton +class CommandBufferOld : public Singleton { public: GLuint drawindirectcmd; @@ -39,7 +39,7 @@ public: //size_t Offset[nb_cascades][nb_materials]; //size_t Size[nb_cascades][nb_materials]; - CommandBuffer() + CommandBufferOld() { glGenBuffers(1, &drawindirectcmd); glBindBuffer(GL_DRAW_INDIRECT_BUFFER, drawindirectcmd); @@ -61,25 +61,25 @@ public: }; -class SolidPassCmd : public CommandBuffer(Material::SHADERTYPE_COUNT)> +class SolidPassCmd : public CommandBufferOld(Material::SHADERTYPE_COUNT)> { public: size_t Offset[Material::SHADERTYPE_COUNT], Size[Material::SHADERTYPE_COUNT]; }; -class ShadowPassCmd : public CommandBuffer(Material::SHADERTYPE_COUNT)> +class ShadowPassCmd : public CommandBufferOld(Material::SHADERTYPE_COUNT)> { public: size_t Offset[4][Material::SHADERTYPE_COUNT], Size[4][Material::SHADERTYPE_COUNT]; }; -class RSMPassCmd : public CommandBuffer(Material::SHADERTYPE_COUNT)> +class RSMPassCmd : public CommandBufferOld(Material::SHADERTYPE_COUNT)> { public: size_t Offset[Material::SHADERTYPE_COUNT], Size[Material::SHADERTYPE_COUNT]; }; -class GlowPassCmd : public CommandBuffer +class GlowPassCmd : public CommandBufferOld { public: size_t Offset, Size;