Removed several singletons and added a CommandBuffer class

This commit is contained in:
Elderme 2015-10-30 15:23:15 +01:00
parent 4452661533
commit 6ba82eaac9
12 changed files with 678 additions and 149 deletions

View File

@ -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<InstanceDataSingleTex>::add(GLMesh *mesh, scene::ISceneNode *node, InstanceDataSingleTex &instance)
{
fillOriginOrientationScale<InstanceDataSingleTex>(node, instance);
instance.Texture = mesh->TextureHandles[0];
}
template<>
void InstanceFiller<InstanceDataDualTex>::add(GLMesh *mesh, scene::ISceneNode *node, InstanceDataDualTex &instance)
{
fillOriginOrientationScale<InstanceDataDualTex>(node, instance);
instance.Texture = mesh->TextureHandles[0];
instance.SecondTexture = mesh->TextureHandles[1];
}
template<>
void InstanceFiller<InstanceDataThreeTex>::add(GLMesh *mesh, scene::ISceneNode *node, InstanceDataThreeTex &instance)
{
fillOriginOrientationScale<InstanceDataThreeTex>(node, instance);
instance.Texture = mesh->TextureHandles[0];
instance.SecondTexture = mesh->TextureHandles[1];
instance.ThirdTexture = mesh->TextureHandles[2];
}
template<>
void InstanceFiller<GlowInstanceData>::add(GLMesh *mesh, scene::ISceneNode *node, GlowInstanceData &instance)
{
fillOriginOrientationScale<GlowInstanceData>(node, instance);
STKMeshSceneNode *nd = dynamic_cast<STKMeshSceneNode*>(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<typename T>
void CommandBuffer::fillMaterial(int material_id,
MeshMap *mesh_map,
std::vector<GLMesh *> &instanced_list,
T *instance_buffer)
{
m_offset[material_id] = m_instance_buffer_offset;
FillInstances<T>(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<int>(Material::SHADERTYPE_COUNT)];
m_size = new size_t[static_cast<int>(Material::SHADERTYPE_COUNT)];
}
void SolidCommandBuffer::fill(MeshMap *mesh_map, std::vector<GLMesh *> 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<int>(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<int>(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<int>(Material::SHADERTYPE_COUNT)];
m_size = new size_t[4 * static_cast<int>(Material::SHADERTYPE_COUNT)];
}
void ShadowCommandBuffer::fill(MeshMap *mesh_map, std::vector<GLMesh *> 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<int>(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<int>(Material::SHADERTYPE_COUNT)];
m_size = new size_t[static_cast<int>(Material::SHADERTYPE_COUNT)];
}
void ReflectiveShadowMapCommandBuffer::fill(MeshMap *mesh_map, std::vector<GLMesh *> 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<int>(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<GLMesh *> 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

View File

@ -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 <irrlicht.h>
#include <unordered_map>
typedef std::vector<std::pair<GLMesh *, irr::scene::ISceneNode*> > InstanceList;
typedef std::unordered_map <irr::scene::IMeshBuffer *, InstanceList > MeshMap;
template<typename InstanceData>
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<typename InstanceData>
struct InstanceFiller
{
static void add(GLMesh *, scene::ISceneNode *, InstanceData &);
};
template<typename T>
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<T>::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<typename T>
void FillInstances( const MeshMap &gathered_GL_mesh,
std::vector<GLMesh *> &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<T>(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<typename T>
void fillMaterial(int material_id,
MeshMap *mesh_map,
std::vector<GLMesh *> &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<int>(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<int>(shader_type)] * sizeof(DrawElementsIndirectCommand)),
(int) m_size[static_cast<int>(shader_type)],
sizeof(DrawElementsIndirectCommand));
}
};
class SolidCommandBuffer: public CommandBuffer
{
public:
SolidCommandBuffer();
void fill(MeshMap *mesh_map, std::vector<GLMesh *> instanced_lists[]);
};
class ShadowCommandBuffer: public CommandBuffer
{
public:
ShadowCommandBuffer();
void fill(MeshMap *mesh_map, std::vector<GLMesh *> instanced_lists[]);
};
class ReflectiveShadowMapCommandBuffer: public CommandBuffer
{
public:
ReflectiveShadowMapCommandBuffer();
void fill(MeshMap *mesh_map, std::vector<GLMesh *> instanced_lists[]);
};
class GlowCommandBuffer: public CommandBuffer
{
public:
GlowCommandBuffer();
void fill(MeshMap *mesh_map, std::vector<GLMesh *> instanced_lists[]);
};
#endif //HEADER_COMMAND_BUFFER_HPP

View File

@ -28,63 +28,6 @@ using namespace irr;
namespace
{
template<typename InstanceData>
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<typename InstanceData>
struct InstanceFiller
{
static void add(GLMesh *, scene::ISceneNode *, InstanceData &);
};
template<>
void InstanceFiller<InstanceDataSingleTex>::add(GLMesh *mesh, scene::ISceneNode *node, InstanceDataSingleTex &Instance)
{
fillOriginOrientationScale<InstanceDataSingleTex>(node, Instance);
Instance.Texture = mesh->TextureHandles[0];
}
template<>
void InstanceFiller<InstanceDataDualTex>::add(GLMesh *mesh, scene::ISceneNode *node, InstanceDataDualTex &Instance)
{
fillOriginOrientationScale<InstanceDataDualTex>(node, Instance);
Instance.Texture = mesh->TextureHandles[0];
Instance.SecondTexture = mesh->TextureHandles[1];
}
template<>
void InstanceFiller<InstanceDataThreeTex>::add(GLMesh *mesh, scene::ISceneNode *node, InstanceDataThreeTex &Instance)
{
fillOriginOrientationScale<InstanceDataThreeTex>(node, Instance);
Instance.Texture = mesh->TextureHandles[0];
Instance.SecondTexture = mesh->TextureHandles[1];
Instance.ThirdTexture = mesh->TextureHandles[2];
}
template<>
void InstanceFiller<GlowInstanceData>::add(GLMesh *mesh, scene::ISceneNode *node, GlowInstanceData &Instance)
{
fillOriginOrientationScale<GlowInstanceData>(node, Instance);
STKMeshSceneNode *nd = dynamic_cast<STKMeshSceneNode*>(node);
Instance.Color = nd->getGlowColor().color;
}
void FixBoundingBoxes(scene::ISceneNode* node)
{
for (scene::ISceneNode *child : node->getChildren())
@ -94,58 +37,7 @@ namespace
}
}
template<typename T>
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<T>::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<typename T>
void FillInstances( const DrawCalls::MeshMap &GatheredGLMesh,
std::vector<GLMesh *> &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<T>(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<GLMesh *> instanced_lists[Material::SHADERTYPE_COUNT];
instanced_lists[static_cast<int>(Material::SHADERTYPE_SOLID)] = ListInstancedMatDefault::getInstance()->SolidPass;
instanced_lists[static_cast<int>(Material::SHADERTYPE_ALPHA_TEST)] = ListInstancedMatAlphaRef::getInstance()->SolidPass;
instanced_lists[static_cast<int>(Material::SHADERTYPE_SOLID_UNLIT)] = ListInstancedMatUnlit::getInstance()->SolidPass;
instanced_lists[static_cast<int>(Material::SHADERTYPE_SPHERE_MAP)] = ListInstancedMatSphereMap::getInstance()->SolidPass;
instanced_lists[static_cast<int>(Material::SHADERTYPE_VEGETATION)] = ListInstancedMatGrass::getInstance()->SolidPass;
instanced_lists[static_cast<int>(Material::SHADERTYPE_DETAIL_MAP)] = ListInstancedMatDetails::getInstance()->SolidPass;
instanced_lists[static_cast<int>(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

View File

@ -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 <irrlicht.h>
#include <unordered_map>
class DrawCalls
{
public:
typedef std::vector<std::pair<GLMesh *, irr::scene::ISceneNode*> > InstanceList;
typedef std::unordered_map <irr::scene::IMeshBuffer *, InstanceList > MeshMap;
GLsync m_sync = 0; //TODO: make it private. Should it be in shader_based_renderer?
@ -41,6 +44,12 @@ private:
std::vector<STKBillboard *> m_billboard_list;
std::vector<ParticleSystemProxy *> 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] ;

View File

@ -21,6 +21,7 @@
#include "graphics/shader.hpp"
#include "graphics/irr_driver.hpp"
#include "graphics/stk_mesh.hpp"
#include "graphics/texture_manager.hpp"
// ----------------------------------------------------------------------------

View File

@ -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"

View File

@ -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<size_t> FirstPassTextures;
static const STK::Tuple<size_t, size_t> SecondPassTextures;
static const STK::Tuple<> ShadowTextures;
static const STK::Tuple<size_t> RSMTextures;
}; // struct DefaultMaterial
const STK::Tuple<size_t> DefaultMaterial::FirstPassTextures
= STK::Tuple<size_t>(1);
const STK::Tuple<size_t, size_t> DefaultMaterial::SecondPassTextures
= STK::Tuple<size_t, size_t>(0, 1);
const STK::Tuple<> DefaultMaterial::ShadowTextures;
const STK::Tuple<size_t> DefaultMaterial::RSMTextures = STK::Tuple<size_t>(0);
*/
#endif //HEADER_MATERIAL_TYPE_HPP

View File

@ -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) {

View File

@ -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();

View File

@ -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();
}
*/

View File

@ -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

View File

@ -30,7 +30,7 @@
#include "utils/singleton.hpp"
template<typename T, int nb_cascades, int nb_materials>
class CommandBuffer : public Singleton<T>
class CommandBufferOld : public Singleton<T>
{
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<SolidPassCmd, 1, static_cast<int>(Material::SHADERTYPE_COUNT)>
class SolidPassCmd : public CommandBufferOld<SolidPassCmd, 1, static_cast<int>(Material::SHADERTYPE_COUNT)>
{
public:
size_t Offset[Material::SHADERTYPE_COUNT], Size[Material::SHADERTYPE_COUNT];
};
class ShadowPassCmd : public CommandBuffer<ShadowPassCmd, 4, static_cast<int>(Material::SHADERTYPE_COUNT)>
class ShadowPassCmd : public CommandBufferOld<ShadowPassCmd, 4, static_cast<int>(Material::SHADERTYPE_COUNT)>
{
public:
size_t Offset[4][Material::SHADERTYPE_COUNT], Size[4][Material::SHADERTYPE_COUNT];
};
class RSMPassCmd : public CommandBuffer<RSMPassCmd, 1, static_cast<int>(Material::SHADERTYPE_COUNT)>
class RSMPassCmd : public CommandBufferOld<RSMPassCmd, 1, static_cast<int>(Material::SHADERTYPE_COUNT)>
{
public:
size_t Offset[Material::SHADERTYPE_COUNT], Size[Material::SHADERTYPE_COUNT];
};
class GlowPassCmd : public CommandBuffer<GlowPassCmd, 1, 1>
class GlowPassCmd : public CommandBufferOld<GlowPassCmd, 1, 1>
{
public:
size_t Offset, Size;