Refactoring of streamer code to integrate texture and vbo memory management in progress.

This commit is contained in:
2014-05-27 22:51:52 -07:00
parent bfefcdd055
commit 37ba588b58
23 changed files with 438 additions and 250 deletions

View File

@@ -116,7 +116,7 @@ void KRAmbientZone::render(KRCamera *pCamera, std::vector<KRPointLight *> &point
std::vector<KRMesh *> sphereModels = getContext().getMeshManager()->getModel("__sphere");
if(sphereModels.size()) {
for(int i=0; i < sphereModels[0]->getSubmeshCount(); i++) {
sphereModels[0]->renderSubmesh(i, renderPass, getName(), "visualize_overlay");
sphereModels[0]->renderSubmesh(i, renderPass, getName(), "visualize_overlay", 1.0f);
}
}

View File

@@ -229,7 +229,7 @@ void KRAudioSource::render(KRCamera *pCamera, std::vector<KRPointLight *> &point
std::vector<KRMesh *> sphereModels = getContext().getMeshManager()->getModel("__sphere");
if(sphereModels.size()) {
for(int i=0; i < sphereModels[0]->getSubmeshCount(); i++) {
sphereModels[0]->renderSubmesh(i, renderPass, getName(), "visualize_overlay");
sphereModels[0]->renderSubmesh(i, renderPass, getName(), "visualize_overlay", 1.0f);
}
}

View File

@@ -68,7 +68,7 @@ void KRBone::render(KRCamera *pCamera, std::vector<KRPointLight *> &point_lights
std::vector<KRMesh *> sphereModels = getContext().getMeshManager()->getModel("__sphere");
if(sphereModels.size()) {
for(int i=0; i < sphereModels[0]->getSubmeshCount(); i++) {
sphereModels[0]->renderSubmesh(i, renderPass, getName(), "visualize_overlay");
sphereModels[0]->renderSubmesh(i, renderPass, getName(), "visualize_overlay", 1.0f);
}
}

View File

@@ -321,7 +321,7 @@ void KRCamera::renderFrame(float deltaTime, GLint renderBufferWidth, GLint rende
getContext().getTextureManager()->selectTexture(0, m_pSkyBoxTexture, 0.0f, KRTexture::TEXTURE_USAGE_SKY_CUBE);
// Render a full screen quad
m_pContext->getMeshManager()->bindVBO(&getContext().getMeshManager()->KRENGINE_VBO_DATA_2D_SQUARE_VERTICES);
m_pContext->getMeshManager()->bindVBO(&getContext().getMeshManager()->KRENGINE_VBO_DATA_2D_SQUARE_VERTICES, 1.0f);
GLDEBUG(glDrawArrays(GL_TRIANGLE_STRIP, 0, 4));
}
@@ -482,7 +482,7 @@ void KRCamera::renderFrame(float deltaTime, GLint renderBufferWidth, GLint rende
KRShader *pVisShader = getContext().getShaderManager()->getShader("visualize_overlay", this, std::vector<KRPointLight *>(), std::vector<KRDirectionalLight *>(), std::vector<KRSpotLight *>(), 0, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, KRNode::RENDER_PASS_FORWARD_TRANSPARENT);
m_pContext->getMeshManager()->bindVBO(&getContext().getMeshManager()->KRENGINE_VBO_DATA_3D_CUBE_VERTICES);
m_pContext->getMeshManager()->bindVBO(&getContext().getMeshManager()->KRENGINE_VBO_DATA_3D_CUBE_VERTICES, 1.0f);
for(unordered_map<KRAABB, int>::iterator itr=m_viewport.getVisibleBounds().begin(); itr != m_viewport.getVisibleBounds().end(); itr++) {
KRMat4 matModel = KRMat4();
matModel.scale((*itr).first.size() * 0.5f);
@@ -716,7 +716,7 @@ void KRCamera::renderPost()
}
// Update attribute values.
m_pContext->getMeshManager()->bindVBO(&getContext().getMeshManager()->KRENGINE_VBO_DATA_2D_SQUARE_VERTICES);
m_pContext->getMeshManager()->bindVBO(&getContext().getMeshManager()->KRENGINE_VBO_DATA_2D_SQUARE_VERTICES, 1.0f);
GLDEBUG(glDrawArrays(GL_TRIANGLE_STRIP, 0, 4));
@@ -755,12 +755,6 @@ void KRCamera::renderPost()
// GLDEBUG(glBindTexture(GL_TEXTURE_2D, 0));
// }
if(m_debug_text_vertices.getSize()) {
m_pContext->getMeshManager()->releaseVBO(m_debug_text_vertices);
}
const char *szText = settings.m_debug_text.c_str();
std::string debug_text;
@@ -907,7 +901,7 @@ void KRCamera::renderPost()
m_pContext->getTextureManager()->selectTexture(0, m_pContext->getTextureManager()->getTexture("font"), 0.0f, KRTexture::TEXTURE_USAGE_UI);
KRDataBlock index_data;
m_pContext->getMeshManager()->bindVBO(m_debug_text_vertices, index_data, (1 << KRMesh::KRENGINE_ATTRIB_VERTEX) | (1 << KRMesh::KRENGINE_ATTRIB_TEXUVA), true);
m_pContext->getMeshManager()->bindVBO(m_debug_text_vertices, index_data, (1 << KRMesh::KRENGINE_ATTRIB_VERTEX) | (1 << KRMesh::KRENGINE_ATTRIB_TEXUVA), true, 1.0f);
GLDEBUG(glDrawArrays(GL_TRIANGLES, 0, vertex_count));
@@ -997,7 +991,6 @@ std::string KRCamera::getDebugText()
long texture_mem_throughput = m_pContext->getTextureManager()->getMemoryTransferedThisFrame();
int vbo_count_active = m_pContext->getMeshManager()->getActiveVBOCount();
int vbo_count_pooled = m_pContext->getMeshManager()->getPoolVBOCount();
long vbo_mem_active = m_pContext->getMeshManager()->getMemActive();
long vbo_mem_used = m_pContext->getMeshManager()->getMemUsed();
long vbo_mem_throughput = m_pContext->getMeshManager()->getMemoryTransferedThisFrame();
@@ -1009,7 +1002,7 @@ std::string KRCamera::getDebugText()
stream << "\n\n\n\t# Active\t# Used\tActive\tUsed\tThroughput\n";
stream << "Textures\t" << texture_count_active << "\t" << texture_count << "\t" << (texture_mem_active / 1024) << " KB\t" << (texture_mem_used / 1024) << " KB\t" << (texture_mem_throughput / 1024) << " KB / frame\n";
stream << "VBO's\t" << vbo_count_active << "\t" << vbo_count_active + vbo_count_pooled << "\t" << (vbo_mem_active / 1024) <<" KB\t" << (vbo_mem_used / 1024) << " KB\t" << (vbo_mem_throughput / 1024) << " KB / frame\n";
stream << "VBO's\t" << vbo_count_active << "\t" << vbo_count_active << "\t" << (vbo_mem_active / 1024) <<" KB\t" << (vbo_mem_used / 1024) << " KB\t" << (vbo_mem_throughput / 1024) << " KB / frame\n";
stream << "\nGPU Total\t\t\t" << (total_mem_active / 1024) << " KB\t" << (total_mem_used / 1024) << " KB\t" << (total_mem_throughput / 1024) << " KB / frame";
}
break;

View File

@@ -217,7 +217,7 @@ void KRCollider::render(KRCamera *pCamera, std::vector<KRPointLight *> &point_li
for(int i=0; i < m_models[0]->getSubmeshCount(); i++) {
m_models[0]->renderSubmesh(i, renderPass, getName(), "visualize_overlay");
m_models[0]->renderSubmesh(i, renderPass, getName(), "visualize_overlay", 1.0f);
}
// Enable alpha blending

View File

@@ -259,13 +259,6 @@ void KRContext::loadResource(std::string path) {
}
}
void KRContext::rotateBuffers(bool new_frame) {
//fprintf(stderr, "Rotating Buffers...\n");
if(!new_frame) GLDEBUG(glFinish());
m_pMeshManager->rotateBuffers(new_frame);
}
void KRContext::detectExtensions() {
m_bDetectedExtensions = true;
@@ -285,7 +278,6 @@ void KRContext::endFrame(float deltaTime)
m_pTextureManager->endFrame(deltaTime);
m_pAnimationManager->endFrame(deltaTime);
m_pMeshManager->endFrame(deltaTime);
rotateBuffers(true);
m_current_frame++;
m_absolute_time += deltaTime;
}
@@ -343,7 +335,7 @@ void KRContext::doStreaming()
{
if(m_streamingEnabled) {
long memoryRemaining = KRENGINE_TARGET_TEXTURE_MEM_MAX;
long memoryRemainingThisFrame = KRENGINE_MAX_TEXTURE_MEM - m_pTextureManager->getMemUsed();
long memoryRemainingThisFrame = KRENGINE_MAX_TEXTURE_MEM - m_pTextureManager->getMemUsed() - m_pMeshManager->getMemUsed();
m_pMeshManager->doStreaming(memoryRemaining, memoryRemainingThisFrame);
m_pTextureManager->doStreaming(memoryRemaining, memoryRemainingThisFrame);
}

View File

@@ -54,8 +54,6 @@ public:
KRCamera *createCamera(int width, int height);
void rotateBuffers(bool new_frame);
enum {
KRENGINE_GL_EXT_texture_storage,
KRENGINE_NUM_EXTENSIONS

View File

@@ -123,7 +123,7 @@ void KRDirectionalLight::render(KRCamera *pCamera, std::vector<KRPointLight *> &
GLDEBUG(glDisable(GL_DEPTH_TEST));
// Render a full screen quad
m_pContext->getMeshManager()->bindVBO(&getContext().getMeshManager()->KRENGINE_VBO_DATA_2D_SQUARE_VERTICES);
m_pContext->getMeshManager()->bindVBO(&getContext().getMeshManager()->KRENGINE_VBO_DATA_2D_SQUARE_VERTICES, 1.0f);
GLDEBUG(glDrawArrays(GL_TRIANGLE_STRIP, 0, 4));
}
}

View File

@@ -230,7 +230,7 @@ void KRLight::render(KRCamera *pCamera, std::vector<KRPointLight *> &point_light
pParticleShader->setUniform(KRShader::KRENGINE_UNIFORM_FLARE_SIZE, m_dust_particle_size);
KRDataBlock particle_index_data;
m_pContext->getMeshManager()->bindVBO(m_pContext->getMeshManager()->getRandomParticles(), particle_index_data, (1 << KRMesh::KRENGINE_ATTRIB_VERTEX) | (1 << KRMesh::KRENGINE_ATTRIB_TEXUVA), true);
m_pContext->getMeshManager()->bindVBO(m_pContext->getMeshManager()->getRandomParticles(), particle_index_data, (1 << KRMesh::KRENGINE_ATTRIB_VERTEX) | (1 << KRMesh::KRENGINE_ATTRIB_TEXUVA), true, 1.0f);
GLDEBUG(glDrawArrays(GL_TRIANGLES, 0, particle_count*3));
}
}
@@ -271,7 +271,7 @@ void KRLight::render(KRCamera *pCamera, std::vector<KRPointLight *> &point_light
pFogShader->setUniform(KRShader::KRENGINE_UNIFORM_LIGHT_COLOR, (m_color * pCamera->settings.volumetric_environment_intensity * m_intensity * -slice_spacing / 1000.0f));
KRDataBlock index_data;
m_pContext->getMeshManager()->bindVBO(m_pContext->getMeshManager()->getVolumetricLightingVertexes(), index_data, (1 << KRMesh::KRENGINE_ATTRIB_VERTEX), true);
m_pContext->getMeshManager()->bindVBO(m_pContext->getMeshManager()->getVolumetricLightingVertexes(), index_data, (1 << KRMesh::KRENGINE_ATTRIB_VERTEX), true, 1.0f);
GLDEBUG(glDrawArrays(GL_TRIANGLES, 0, slice_count*6));
}
@@ -301,7 +301,7 @@ void KRLight::render(KRCamera *pCamera, std::vector<KRPointLight *> &point_light
std::vector<KRMesh *> sphereModels = getContext().getMeshManager()->getModel("__sphere");
if(sphereModels.size()) {
for(int i=0; i < sphereModels[0]->getSubmeshCount(); i++) {
sphereModels[0]->renderSubmesh(i, renderPass, getName(), "occlusion_test");
sphereModels[0]->renderSubmesh(i, renderPass, getName(), "occlusion_test", 1.0f);
}
}
@@ -341,7 +341,7 @@ void KRLight::render(KRCamera *pCamera, std::vector<KRPointLight *> &point_light
pShader->setUniform(KRShader::KRENGINE_UNIFORM_MATERIAL_ALPHA, 1.0f);
pShader->setUniform(KRShader::KRENGINE_UNIFORM_FLARE_SIZE, m_flareSize);
m_pContext->getTextureManager()->selectTexture(0, m_pFlareTexture, 0.0f, KRTexture::TEXTURE_USAGE_LIGHT_FLARE);
m_pContext->getMeshManager()->bindVBO(&getContext().getMeshManager()->KRENGINE_VBO_DATA_2D_SQUARE_VERTICES);
m_pContext->getMeshManager()->bindVBO(&getContext().getMeshManager()->KRENGINE_VBO_DATA_2D_SQUARE_VERTICES, 1.0f);
GLDEBUG(glDrawArrays(GL_TRIANGLE_STRIP, 0, 4));
}
}

View File

@@ -49,6 +49,7 @@ KRMesh::KRMesh(KRContext &context, std::string name) : KRResource(context, name)
m_pData = NULL;
m_pMetaData = NULL;
m_pIndexBaseData = NULL;
m_constant = false;
}
@@ -59,6 +60,7 @@ KRMesh::KRMesh(KRContext &context, std::string name, KRDataBlock *data) : KRReso
m_pData = NULL;
m_pMetaData = NULL;
m_pIndexBaseData = NULL;
m_constant = false;
loadPack(data);
}
@@ -194,6 +196,28 @@ void KRMesh::preStream(float lodCoverage)
for(std::set<KRMaterial *>::iterator mat_itr = m_uniqueMaterials.begin(); mat_itr != m_uniqueMaterials.end(); mat_itr++) {
(*mat_itr)->preStream(lodCoverage);
}
int cSubmeshes = m_submeshes.size();
for(int iSubmesh=0; iSubmesh<cSubmeshes; iSubmesh++) {
for(auto vbo_data_itr = m_submeshes[iSubmesh]->vbo_data_blocks.begin(); vbo_data_itr != m_submeshes[iSubmesh]->vbo_data_blocks.end(); vbo_data_itr++) {
(*vbo_data_itr)->resetPoolExpiry(lodCoverage);
}
}
}
void KRMesh::load()
{
// Load immediately into the GPU rather than passing through the streamer
getSubmeshes();
getMaterials();
int cSubmeshes = m_submeshes.size();
for(int iSubmesh=0; iSubmesh<cSubmeshes; iSubmesh++) {
for(auto vbo_data_itr = m_submeshes[iSubmesh]->vbo_data_blocks.begin(); vbo_data_itr != m_submeshes[iSubmesh]->vbo_data_blocks.end(); vbo_data_itr++) {
(*vbo_data_itr)->resetPoolExpiry(1.0f);
(*vbo_data_itr)->load();
}
}
}
kraken_stream_level KRMesh::getStreamLevel()
@@ -205,6 +229,22 @@ kraken_stream_level KRMesh::getStreamLevel()
for(std::set<KRMaterial *>::iterator mat_itr = m_uniqueMaterials.begin(); mat_itr != m_uniqueMaterials.end(); mat_itr++) {
stream_level = KRMIN(stream_level, (*mat_itr)->getStreamLevel());
}
bool all_vbo_data_loaded = true;
bool vbo_data_loaded = false;
int cSubmeshes = m_submeshes.size();
for(int iSubmesh=0; iSubmesh<cSubmeshes; iSubmesh++) {
for(auto vbo_data_itr = m_submeshes[iSubmesh]->vbo_data_blocks.begin(); vbo_data_itr != m_submeshes[iSubmesh]->vbo_data_blocks.end(); vbo_data_itr++) {
if((*vbo_data_itr)->isVBOReady()) {
vbo_data_loaded = true;
} else {
all_vbo_data_loaded = false;
}
}
}
if(!vbo_data_loaded || !all_vbo_data_loaded) {
stream_level = kraken_stream_level::STREAM_LEVEL_OUT;
}
return stream_level;
}
@@ -213,58 +253,61 @@ void KRMesh::render(const std::string &object_name, KRCamera *pCamera, std::vect
//fprintf(stderr, "Rendering model: %s\n", m_name.c_str());
if(renderPass != KRNode::RENDER_PASS_ADDITIVE_PARTICLES && renderPass != KRNode::RENDER_PASS_PARTICLE_OCCLUSION && renderPass != KRNode::RENDER_PASS_VOLUMETRIC_EFFECTS_ADDITIVE) {
getSubmeshes();
getMaterials();
int cSubmeshes = m_submeshes.size();
if(renderPass == KRNode::RENDER_PASS_SHADOWMAP) {
for(int iSubmesh=0; iSubmesh<cSubmeshes; iSubmesh++) {
KRMaterial *pMaterial = m_materials[iSubmesh];
if(pMaterial != NULL) {
if(!pMaterial->isTransparent()) {
// Exclude transparent and semi-transparent meshes from shadow maps
renderSubmesh(iSubmesh, renderPass, object_name, pMaterial->getName());
}
}
}
if(getStreamLevel() == kraken_stream_level::STREAM_LEVEL_OUT) {
preStream(lod_coverage);
} else {
// Apply submeshes in per-material batches to reduce number of state changes
for(std::set<KRMaterial *>::iterator mat_itr = m_uniqueMaterials.begin(); mat_itr != m_uniqueMaterials.end(); mat_itr++) {
getSubmeshes();
getMaterials();
int cSubmeshes = m_submeshes.size();
if(renderPass == KRNode::RENDER_PASS_SHADOWMAP) {
for(int iSubmesh=0; iSubmesh<cSubmeshes; iSubmesh++) {
KRMaterial *pMaterial = m_materials[iSubmesh];
if(pMaterial != NULL && pMaterial == (*mat_itr)) {
if((!pMaterial->isTransparent() && renderPass != KRNode::RENDER_PASS_FORWARD_TRANSPARENT) || (pMaterial->isTransparent() && renderPass == KRNode::RENDER_PASS_FORWARD_TRANSPARENT)) {
std::vector<KRMat4> bone_bind_poses;
for(int i=0; i < bones.size(); i++) {
bone_bind_poses.push_back(getBoneBindPose(i));
}
if(pMaterial->bind(pCamera, point_lights, directional_lights, spot_lights, bones, bone_bind_poses, viewport, matModel, pLightMap, renderPass, rim_color, rim_power, lod_coverage)) {
switch(pMaterial->getAlphaMode()) {
case KRMaterial::KRMATERIAL_ALPHA_MODE_OPAQUE: // Non-transparent materials
case KRMaterial::KRMATERIAL_ALPHA_MODE_TEST: // Alpha in diffuse texture is interpreted as punch-through when < 0.5
renderSubmesh(iSubmesh, renderPass, object_name, pMaterial->getName());
break;
case KRMaterial::KRMATERIAL_ALPHA_MODE_BLENDONESIDE: // Blended alpha with backface culling
renderSubmesh(iSubmesh, renderPass, object_name, pMaterial->getName());
break;
case KRMaterial::KRMATERIAL_ALPHA_MODE_BLENDTWOSIDE: // Blended alpha rendered in two passes. First pass renders backfaces; second pass renders frontfaces.
// Render back faces first
GLDEBUG(glCullFace(GL_FRONT));
renderSubmesh(iSubmesh, renderPass, object_name, pMaterial->getName());
if(pMaterial != NULL) {
// Render front faces second
GLDEBUG(glCullFace(GL_BACK));
renderSubmesh(iSubmesh, renderPass, object_name, pMaterial->getName());
break;
if(!pMaterial->isTransparent()) {
// Exclude transparent and semi-transparent meshes from shadow maps
renderSubmesh(iSubmesh, renderPass, object_name, pMaterial->getName(), lod_coverage);
}
}
}
} else {
// Apply submeshes in per-material batches to reduce number of state changes
for(std::set<KRMaterial *>::iterator mat_itr = m_uniqueMaterials.begin(); mat_itr != m_uniqueMaterials.end(); mat_itr++) {
for(int iSubmesh=0; iSubmesh<cSubmeshes; iSubmesh++) {
KRMaterial *pMaterial = m_materials[iSubmesh];
if(pMaterial != NULL && pMaterial == (*mat_itr)) {
if((!pMaterial->isTransparent() && renderPass != KRNode::RENDER_PASS_FORWARD_TRANSPARENT) || (pMaterial->isTransparent() && renderPass == KRNode::RENDER_PASS_FORWARD_TRANSPARENT)) {
std::vector<KRMat4> bone_bind_poses;
for(int i=0; i < bones.size(); i++) {
bone_bind_poses.push_back(getBoneBindPose(i));
}
if(pMaterial->bind(pCamera, point_lights, directional_lights, spot_lights, bones, bone_bind_poses, viewport, matModel, pLightMap, renderPass, rim_color, rim_power, lod_coverage)) {
switch(pMaterial->getAlphaMode()) {
case KRMaterial::KRMATERIAL_ALPHA_MODE_OPAQUE: // Non-transparent materials
case KRMaterial::KRMATERIAL_ALPHA_MODE_TEST: // Alpha in diffuse texture is interpreted as punch-through when < 0.5
renderSubmesh(iSubmesh, renderPass, object_name, pMaterial->getName(), lod_coverage);
break;
case KRMaterial::KRMATERIAL_ALPHA_MODE_BLENDONESIDE: // Blended alpha with backface culling
renderSubmesh(iSubmesh, renderPass, object_name, pMaterial->getName(), lod_coverage);
break;
case KRMaterial::KRMATERIAL_ALPHA_MODE_BLENDTWOSIDE: // Blended alpha rendered in two passes. First pass renders backfaces; second pass renders frontfaces.
// Render back faces first
GLDEBUG(glCullFace(GL_FRONT));
renderSubmesh(iSubmesh, renderPass, object_name, pMaterial->getName(), lod_coverage);
// Render front faces second
GLDEBUG(glCullFace(GL_BACK));
renderSubmesh(iSubmesh, renderPass, object_name, pMaterial->getName(), lod_coverage);
break;
}
}
}
}
}
}
@@ -303,21 +346,90 @@ void KRMesh::getSubmeshes() {
//fprintf(stderr, "Submesh material: \"%s\"\n", pSubmesh->szMaterialName);
m_submeshes.push_back(pSubmesh);
}
createDataBlocks(m_constant ? KRMeshManager::KRVBOData::CONSTANT : KRMeshManager::KRVBOData::STREAMING);
}
}
void KRMesh::renderSubmesh(int iSubmesh, KRNode::RenderPass renderPass, const std::string &object_name, const std::string &material_name) {
//m_pData->lock();
void KRMesh::createDataBlocks(KRMeshManager::KRVBOData::vbo_type t)
{
int cSubmeshes = m_submeshes.size();
for(int iSubmesh=0; iSubmesh < cSubmeshes; iSubmesh++) {
Submesh *pSubmesh = m_submeshes[iSubmesh];
int cVertexes = pSubmesh->vertex_count;
int vertex_data_offset = getVertexDataOffset();
int index_data_offset = getIndexDataOffset();
pack_header *pHeader = getHeader();
int32_t vertex_attrib_flags = pHeader->vertex_attrib_flags;
int32_t vertex_count = pHeader->vertex_count;
int vbo_index=0;
if(getModelFormat() == KRENGINE_MODEL_FORMAT_INDEXED_TRIANGLES) {
int index_group = getSubmesh(iSubmesh)->index_group;
int index_group_offset = getSubmesh(iSubmesh)->index_group_offset;
while(cVertexes > 0) {
int start_index_offset, start_vertex_offset, index_count, vertex_count;
getIndexedRange(index_group++, start_index_offset, start_vertex_offset, index_count, vertex_count);
if(m_submeshes[iSubmesh]->vertex_data_blocks.size() <= vbo_index) {
KRDataBlock *vertex_data_block = m_pData->getSubBlock(vertex_data_offset + start_vertex_offset * m_vertex_size, vertex_count * m_vertex_size);
KRDataBlock *index_data_block = m_pData->getSubBlock(index_data_offset + start_index_offset * 2, index_count * 2);
KRMeshManager::KRVBOData *vbo_data_block = new KRMeshManager::KRVBOData(getContext().getMeshManager(), *vertex_data_block, *index_data_block, vertex_attrib_flags, true, t);
m_submeshes[iSubmesh]->vertex_data_blocks.push_back(vertex_data_block);
m_submeshes[iSubmesh]->index_data_blocks.push_back(index_data_block);
m_submeshes[iSubmesh]->vbo_data_blocks.push_back(vbo_data_block);
}
vbo_index++;
int vertex_draw_count = cVertexes;
if(vertex_draw_count > index_count - index_group_offset) vertex_draw_count = index_count - index_group_offset;
cVertexes -= vertex_draw_count;
index_group_offset = 0;
}
} else {
int cBuffers = (vertex_count + MAX_VBO_SIZE - 1) / MAX_VBO_SIZE;
int iVertex = pSubmesh->start_vertex;
int iBuffer = iVertex / MAX_VBO_SIZE;
iVertex = iVertex % MAX_VBO_SIZE;
while(cVertexes > 0) {
GLsizei cBufferVertexes = iBuffer < cBuffers - 1 ? MAX_VBO_SIZE : vertex_count % MAX_VBO_SIZE;
int vertex_size = m_vertex_size;
if(m_submeshes[iSubmesh]->vertex_data_blocks.size() <= vbo_index) {
KRDataBlock *index_data_block = NULL;
KRDataBlock *vertex_data_block = m_pData->getSubBlock(vertex_data_offset + iBuffer * MAX_VBO_SIZE * vertex_size, vertex_size * cBufferVertexes);
KRMeshManager::KRVBOData *vbo_data_block = new KRMeshManager::KRVBOData(getContext().getMeshManager(), *vertex_data_block, *index_data_block, vertex_attrib_flags, true, t);
m_submeshes[iSubmesh]->vertex_data_blocks.push_back(vertex_data_block);
m_submeshes[iSubmesh]->vbo_data_blocks.push_back(vbo_data_block);
}
vbo_index++;
if(iVertex + cVertexes >= MAX_VBO_SIZE) {
assert(iVertex + (MAX_VBO_SIZE - iVertex) <= cBufferVertexes);
cVertexes -= (MAX_VBO_SIZE - iVertex);
iVertex = 0;
iBuffer++;
} else {
assert(iVertex + cVertexes <= cBufferVertexes);
cVertexes = 0;
}
}
}
}
}
void KRMesh::renderSubmesh(int iSubmesh, KRNode::RenderPass renderPass, const std::string &object_name, const std::string &material_name, float lodCoverage) {
getSubmeshes();
Submesh *pSubmesh = m_submeshes[iSubmesh];
int cVertexes = pSubmesh->vertex_count;
// fprintf(stderr, "start - object: %s material: %s vertices: %i\n", object_name.c_str(), material_name.c_str(), cVertexes);
int vertex_data_offset = getVertexDataOffset();
int index_data_offset = getIndexDataOffset();
pack_header *pHeader = getHeader();
int32_t vertex_attrib_flags = pHeader->vertex_attrib_flags;
int32_t vertex_count = pHeader->vertex_count;
int vbo_index=0;
if(getModelFormat() == KRENGINE_MODEL_FORMAT_INDEXED_TRIANGLES) {
@@ -329,20 +441,10 @@ void KRMesh::renderSubmesh(int iSubmesh, KRNode::RenderPass renderPass, const st
int start_index_offset, start_vertex_offset, index_count, vertex_count;
getIndexedRange(index_group++, start_index_offset, start_vertex_offset, index_count, vertex_count);
KRMeshManager::KRVBOData *vbo_data_block = NULL;
if(m_submeshes[iSubmesh]->vertex_data_blocks.size() <= vbo_index) {
KRDataBlock *vertex_data_block = m_pData->getSubBlock(vertex_data_offset + start_vertex_offset * m_vertex_size, vertex_count * m_vertex_size);
KRDataBlock *index_data_block = m_pData->getSubBlock(index_data_offset + start_index_offset * 2, index_count * 2);
vbo_data_block = new KRMeshManager::KRVBOData(getContext().getMeshManager(), *vertex_data_block, *index_data_block, vertex_attrib_flags, true, false);
m_submeshes[iSubmesh]->vertex_data_blocks.push_back(vertex_data_block);
m_submeshes[iSubmesh]->index_data_blocks.push_back(index_data_block);
m_submeshes[iSubmesh]->vbo_data_blocks.push_back(vbo_data_block);
} else {
vbo_data_block = m_submeshes[iSubmesh]->vbo_data_blocks[vbo_index];
}
vbo_index++;
KRMeshManager::KRVBOData *vbo_data_block = m_submeshes[iSubmesh]->vbo_data_blocks[vbo_index++];
assert(vbo_data_block->isVBOReady());
m_pContext->getMeshManager()->bindVBO(vbo_data_block);
m_pContext->getMeshManager()->bindVBO(vbo_data_block, lodCoverage);
int vertex_draw_count = cVertexes;
@@ -355,28 +457,16 @@ void KRMesh::renderSubmesh(int iSubmesh, KRNode::RenderPass renderPass, const st
}
} else {
int cBuffers = (vertex_count + MAX_VBO_SIZE - 1) / MAX_VBO_SIZE;
int cBuffers = (cVertexes + MAX_VBO_SIZE - 1) / MAX_VBO_SIZE;
int iVertex = pSubmesh->start_vertex;
int iBuffer = iVertex / MAX_VBO_SIZE;
iVertex = iVertex % MAX_VBO_SIZE;
while(cVertexes > 0) {
GLsizei cBufferVertexes = iBuffer < cBuffers - 1 ? MAX_VBO_SIZE : vertex_count % MAX_VBO_SIZE;
int vertex_size = m_vertex_size;
GLsizei cBufferVertexes = iBuffer < cBuffers - 1 ? MAX_VBO_SIZE : cVertexes % MAX_VBO_SIZE;
KRMeshManager::KRVBOData *vbo_data_block = NULL;
if(m_submeshes[iSubmesh]->vertex_data_blocks.size() <= vbo_index) {
KRDataBlock *index_data_block = NULL;
KRDataBlock *vertex_data_block = m_pData->getSubBlock(vertex_data_offset + iBuffer * MAX_VBO_SIZE * vertex_size, vertex_size * cBufferVertexes);
vbo_data_block = new KRMeshManager::KRVBOData(getContext().getMeshManager(), *vertex_data_block, *index_data_block, vertex_attrib_flags, true, false);
m_submeshes[iSubmesh]->vertex_data_blocks.push_back(vertex_data_block);
m_submeshes[iSubmesh]->vbo_data_blocks.push_back(vbo_data_block);
} else {
vbo_data_block = m_submeshes[iSubmesh]->vbo_data_blocks[vbo_index];
}
vbo_index++;
m_pContext->getMeshManager()->bindVBO(vbo_data_block);
KRMeshManager::KRVBOData *vbo_data_block = m_submeshes[iSubmesh]->vbo_data_blocks[vbo_index++];
assert(vbo_data_block->isVBOReady());
m_pContext->getMeshManager()->bindVBO(vbo_data_block, lodCoverage);
if(iVertex + cVertexes >= MAX_VBO_SIZE) {
@@ -422,7 +512,6 @@ void KRMesh::renderSubmesh(int iSubmesh, KRNode::RenderPass renderPass, const st
}
}
//m_pData->unlock();
}
void KRMesh::LoadData(const KRMesh::mesh_info &mi, bool calculate_normals, bool calculate_tangents) {

View File

@@ -129,15 +129,13 @@ public:
void optimize();
void optimizeIndexes();
void renderSubmesh(int iSubmesh, KRNode::RenderPass renderPass, const std::string &object_name, const std::string &material_name);
void renderSubmesh(int iSubmesh, KRNode::RenderPass renderPass, const std::string &object_name, const std::string &material_name, float lodCoverage);
GLfloat getMaxDimension();
KRVector3 getMinPoint() const;
KRVector3 getMaxPoint() const;
class Submesh {
public:
Submesh() {};
@@ -220,6 +218,12 @@ public:
bool sphereCast(const KRMat4 &model_to_world, const KRVector3 &v0, const KRVector3 &v1, float radius, KRHitInfo &hitinfo) const;
static int GetLODCoverage(const std::string &name);
void load(); // Load immediately into the GPU rather than passing through the streamer
protected:
bool m_constant; // TRUE if this should be always loaded and should not be passed through the streamer
private:
KRDataBlock *m_pData;
KRDataBlock *m_pMetaData;
@@ -280,6 +284,9 @@ private:
void releaseData();
void createDataBlocks(KRMeshManager::KRVBOData::vbo_type t);
};

View File

@@ -34,8 +34,9 @@
KRMeshCube::KRMeshCube(KRContext &context) : KRMesh(context, "__cube")
{
KRMesh::mesh_info mi;
m_constant = true;
KRMesh::mesh_info mi;
mi.vertices.push_back(KRVector3(1.0, 1.0, 1.0));
mi.vertices.push_back(KRVector3(-1.0, 1.0, 1.0));

View File

@@ -42,6 +42,8 @@ KRMeshManager::KRMeshManager(KRContext &context) : KRContextObject(context) {
m_currentVBO = NULL;
m_vboMemUsed = 0;
m_memoryTransferredThisFrame = 0;
m_first_frame = true;
m_streamerComplete = true;
addModel(new KRMeshCube(context)); // FINDME - HACK! This needs to be fixed, as it currently segfaults
addModel(new KRMeshQuad(context)); // FINDME - HACK! This needs to be fixed, as it currently segfaults
@@ -76,7 +78,7 @@ KRMeshManager::KRMeshManager(KRContext &context) : KRContextObject(context) {
memcpy(KRENGINE_VBO_3D_CUBE_VERTICES.getStart(), _KRENGINE_VBO_3D_CUBE_VERTEX_DATA, sizeof(GLfloat) * 3 * 14);
KRENGINE_VBO_3D_CUBE_VERTICES.unlock();
KRENGINE_VBO_DATA_3D_CUBE_VERTICES.init(this, KRENGINE_VBO_3D_CUBE_VERTICES, KRENGINE_VBO_3D_CUBE_INDEXES, KRENGINE_VBO_3D_CUBE_ATTRIBS, false, false);
KRENGINE_VBO_DATA_3D_CUBE_VERTICES.init(this, KRENGINE_VBO_3D_CUBE_VERTICES, KRENGINE_VBO_3D_CUBE_INDEXES, KRENGINE_VBO_3D_CUBE_ATTRIBS, false, KRVBOData::CONSTANT);
@@ -92,7 +94,7 @@ KRMeshManager::KRMeshManager(KRContext &context) : KRContextObject(context) {
memcpy(KRENGINE_VBO_2D_SQUARE_VERTICES.getStart(), _KRENGINE_VBO_2D_SQUARE_VERTEX_DATA, sizeof(GLfloat) * 5 * 4);
KRENGINE_VBO_2D_SQUARE_VERTICES.unlock();
KRENGINE_VBO_DATA_2D_SQUARE_VERTICES.init(this, KRENGINE_VBO_2D_SQUARE_VERTICES, KRENGINE_VBO_2D_SQUARE_INDEXES, KRENGINE_VBO_2D_SQUARE_ATTRIBS, false, false);
KRENGINE_VBO_DATA_2D_SQUARE_VERTICES.init(this, KRENGINE_VBO_2D_SQUARE_VERTICES, KRENGINE_VBO_2D_SQUARE_INDEXES, KRENGINE_VBO_2D_SQUARE_ATTRIBS, false, KRVBOData::CONSTANT);
}
@@ -151,6 +153,7 @@ void KRMeshManager::unbindVBO() {
}
}
/*
void KRMeshManager::releaseVBO(KRDataBlock &data)
{
if(m_currentVBO) {
@@ -159,32 +162,34 @@ void KRMeshManager::releaseVBO(KRDataBlock &data)
}
}
KRVBOData *vbo_to_release = NULL;
if(m_vbosActive.find(&data) != m_vbosActive.end()) {
KRContext::Log(KRContext::LOG_LEVEL_WARNING, "glFinish called due to releasing a VBO that is active in the current frame.");
GLDEBUG(glFinish());
// The VBO is active
vbo_to_release = m_vbosActive[&data];
KRVBOData *vbo_to_release = m_vbosActive[&data];
m_vbosActive.erase(&data);
} else {
// The VBO is inactive
vbo_to_release = m_vbosPool[&data];
m_vbosPool.erase(&data);
}
if(vbo_to_release) {
m_vboMemUsed -= vbo_to_release->getSize();
vbo_to_release->unload();
if(vbo_to_release->isTemporary()) {
delete vbo_to_release;
switch(vbo_to_release->getType()) {
case KRVBOData::STREAMING:
vbo_to_release->unload();
break;
case KRVBOData::TEMPORARY:
delete vbo_to_release;
break;
case KRVBOData::CONSTANT:
// CONSTANT VBO's are not unloaded
break;
}
}
}
*/
void KRMeshManager::bindVBO(KRVBOData *vbo_data)
void KRMeshManager::bindVBO(KRVBOData *vbo_data, float lodCoverage)
{
vbo_data->resetPoolExpiry(lodCoverage);
bool vbo_changed = false;
if(m_currentVBO == NULL) {
vbo_changed = true;
@@ -198,57 +203,148 @@ void KRMeshManager::bindVBO(KRVBOData *vbo_data)
if(m_vbosActive.find(vbo_data->m_data) != m_vbosActive.end()) {
m_currentVBO = m_vbosActive[vbo_data->m_data];
m_currentVBO->bind();
} else if(m_vbosPool.find(vbo_data->m_data) != m_vbosPool.end()) {
m_currentVBO = m_vbosPool[vbo_data->m_data];
m_vbosPool.erase(vbo_data->m_data);
m_vbosActive[vbo_data->m_data] = m_currentVBO;
m_currentVBO->bind();
} else {
while(m_vbosPool.size() + m_vbosActive.size() + 1 >= KRContext::KRENGINE_MAX_VBO_HANDLES || m_vboMemUsed + vbo_data->getSize() >= KRContext::KRENGINE_MAX_VBO_MEM) {
if(m_vbosPool.empty()) {
KRContext::Log(KRContext::LOG_LEVEL_WARNING, "flushBuffers due to VBO exhaustion...");
m_pContext->rotateBuffers(false);
}
unordered_map<KRDataBlock *, KRVBOData *>::iterator first_itr = m_vbosPool.begin();
KRVBOData *firstVBO = first_itr->second;
m_vbosPool.erase(first_itr);
m_vboMemUsed -= firstVBO->getSize();
firstVBO->unload();
if(firstVBO->isTemporary()) {
delete firstVBO;
}
// fprintf(stderr, "VBO Swapping...\n");
}
used_vbo_data = true;
m_currentVBO = vbo_data;
m_currentVBO->load();
m_memoryTransferredThisFrame += m_currentVBO->getSize();
m_vboMemUsed += m_currentVBO->getSize();
m_vbosActive[vbo_data->m_data] = m_currentVBO;
}
m_currentVBO->bind();
}
if(!used_vbo_data && vbo_data->isTemporary()) {
if(!used_vbo_data && vbo_data->getType() == KRVBOData::TEMPORARY) {
delete vbo_data;
}
}
void KRMeshManager::bindVBO(KRDataBlock &data, KRDataBlock &index_data, int vertex_attrib_flags, bool static_vbo)
void KRMeshManager::startFrame(float deltaTime)
{
KRVBOData *vbo_data = new KRVBOData(this, data, index_data, vertex_attrib_flags, static_vbo, true);
bindVBO(vbo_data);
m_memoryTransferredThisFrame = 0;
if(m_draw_call_log_used) {
// Only log draw calls on the next frame if the draw call log was used on last frame
m_draw_call_log_used = false;
m_draw_call_logging_enabled = true;
}
m_draw_calls.clear();
if(m_first_frame) {
m_first_frame = false;
firstFrame();
}
// TODO - Implement proper double-buffering to reduce copy operations
m_streamerFenceMutex.lock();
if(m_streamerComplete) {
assert(m_activeVBOs_streamer_copy.size() == 0); // The streamer should have emptied this if it really did complete
const long KRENGINE_VBO_EXPIRY_FRAMES = 30;
std::set<KRVBOData *> expiredVBOs;
for(auto itr=m_vbosActive.begin(); itr != m_vbosActive.end(); itr++) {
KRVBOData *activeVBO = (*itr).second;
activeVBO->_swapHandles();
if(activeVBO->getLastFrameUsed() + KRENGINE_VBO_EXPIRY_FRAMES < getContext().getCurrentFrame()) {
// Expire VBO's that haven't been used in a long time
switch(activeVBO->getType()) {
case KRVBOData::STREAMING:
// TODO - Move to KRVBOData::unload()
if(activeVBO->isVBOLoaded()) {
m_vboMemUsed -= activeVBO->getSize();
}
activeVBO->unload();
break;
case KRVBOData::TEMPORARY:
// TODO - Move to KRVBOData::unload()
if(activeVBO->isVBOLoaded()) {
m_vboMemUsed -= activeVBO->getSize();
}
delete activeVBO;
break;
case KRVBOData::CONSTANT:
// CONSTANT VBO's are not unloaded
break;
}
expiredVBOs.insert(activeVBO);
} else {
if(activeVBO->getType() == KRVBOData::STREAMING) {
float priority = activeVBO->getStreamPriority();
m_activeVBOs_streamer_copy.push_back(std::pair<float, KRVBOData *>(priority, activeVBO));
}
}
}
for(std::set<KRVBOData *>::iterator itr=expiredVBOs.begin(); itr != expiredVBOs.end(); itr++) {
m_vbosActive.erase((*itr)->m_data);
}
if(m_activeVBOs_streamer_copy.size() > 0) {
m_streamerComplete = false;
}
}
m_streamerFenceMutex.unlock();
}
void KRMeshManager::endFrame(float deltaTime)
{
}
void KRMeshManager::firstFrame()
{
KRENGINE_VBO_DATA_3D_CUBE_VERTICES.load();
KRENGINE_VBO_DATA_2D_SQUARE_VERTICES.load();
getModel("__sphere")[0]->load();
getModel("__cube")[0]->load();
getModel("__quad")[0]->load();
}
void KRMeshManager::doStreaming(long &memoryRemaining, long &memoryRemainingThisFrame)
{
// TODO - Implement proper double-buffering to reduce copy operations
m_streamerFenceMutex.lock();
m_activeVBOs_streamer = std::move(m_activeVBOs_streamer_copy);
m_streamerFenceMutex.unlock();
if(m_activeVBOs_streamer.size() > 0) {
balanceVBOMemory(memoryRemaining, memoryRemainingThisFrame);
m_streamerFenceMutex.lock();
m_streamerComplete = true;
m_streamerFenceMutex.unlock();
}
}
void KRMeshManager::balanceVBOMemory(long &memoryRemaining, long &memoryRemainingThisFrame)
{
std::sort(m_activeVBOs_streamer.begin(), m_activeVBOs_streamer.end(), std::greater<std::pair<float, KRVBOData *>>());
for(auto vbo_itr = m_activeVBOs_streamer.begin(); memoryRemainingThisFrame > 0 && vbo_itr != m_activeVBOs_streamer.end(); vbo_itr++) {
KRVBOData *vbo_data = (*vbo_itr).second;
if(!vbo_data->isVBOLoaded()) {
long vbo_size = vbo_data->getSize();
if(memoryRemainingThisFrame > vbo_size) {
vbo_data->load();
memoryRemainingThisFrame -= vbo_size;
memoryRemaining -= vbo_size;
}
}
}
glFinish();
}
void KRMeshManager::bindVBO(KRDataBlock &data, KRDataBlock &index_data, int vertex_attrib_flags, bool static_vbo, float lodCoverage)
{
KRVBOData *vbo_data = new KRVBOData(this, data, index_data, vertex_attrib_flags, static_vbo, KRVBOData::TEMPORARY);
vbo_data->load();
bindVBO(vbo_data, lodCoverage);
}
void KRMeshManager::configureAttribs(__int32_t attributes)
@@ -334,17 +430,6 @@ long KRMeshManager::getMemActive()
return mem_active;
}
void KRMeshManager::rotateBuffers(bool new_frame)
{
m_vbosPool.insert(m_vbosActive.begin(), m_vbosActive.end());
m_vbosActive.clear();
if(m_currentVBO != NULL) {
// Ensure that the currently active VBO does not get flushed to free memory
m_vbosPool.erase(m_currentVBO->m_data);
m_vbosActive[m_currentVBO->m_data] = m_currentVBO;
}
}
KRDataBlock &KRMeshManager::getVolumetricLightingVertexes()
{
if(m_volumetricLightingVertexData.getSize() == 0) {
@@ -429,23 +514,6 @@ KRDataBlock &KRMeshManager::getRandomParticles()
return m_randomParticleVertexData;
}
void KRMeshManager::startFrame(float deltaTime)
{
m_memoryTransferredThisFrame = 0;
if(m_draw_call_log_used) {
// Only log draw calls on the next frame if the draw call log was used on last frame
m_draw_call_log_used = false;
m_draw_call_logging_enabled = true;
}
m_draw_calls.clear();
}
void KRMeshManager::endFrame(float deltaTime)
{
}
long KRMeshManager::getMemoryTransferedThisFrame()
{
return m_memoryTransferredThisFrame;
@@ -457,11 +525,6 @@ int KRMeshManager::getActiveVBOCount()
return m_vbosActive.size();
}
int KRMeshManager::getPoolVBOCount()
{
return m_vbosPool.size();
}
void KRMeshManager::log_draw_call(KRNode::RenderPass pass, const std::string &object_name, const std::string &material_name, int vertex_count)
{
if(m_draw_call_logging_enabled) {
@@ -480,16 +543,12 @@ std::vector<KRMeshManager::draw_call_info> KRMeshManager::getDrawCalls()
return m_draw_calls;
}
void KRMeshManager::doStreaming(long &memoryRemaining, long &memoryRemainingThisFrame)
{
}
KRMeshManager::KRVBOData::KRVBOData()
{
m_is_vbo_loaded = false;
m_is_vbo_ready = false;
m_manager = NULL;
m_temp_vbo = false;
m_static_vbo = false;
m_type = STREAMING;
m_data = NULL;
m_index_data = NULL;
m_vertex_attrib_flags = 0;
@@ -502,15 +561,15 @@ KRMeshManager::KRVBOData::KRVBOData()
m_last_frame_max_lod_coverage = 0.0f;
}
KRMeshManager::KRVBOData::KRVBOData(KRMeshManager *manager, KRDataBlock &data, KRDataBlock &index_data, int vertex_attrib_flags, bool static_vbo, bool temp_vbo)
KRMeshManager::KRVBOData::KRVBOData(KRMeshManager *manager, KRDataBlock &data, KRDataBlock &index_data, int vertex_attrib_flags, bool static_vbo, vbo_type t)
{
init(manager, data,index_data,vertex_attrib_flags, static_vbo, temp_vbo);
init(manager, data,index_data,vertex_attrib_flags, static_vbo, t);
}
void KRMeshManager::KRVBOData::init(KRMeshManager *manager, KRDataBlock &data, KRDataBlock &index_data, int vertex_attrib_flags, bool static_vbo, bool temp_vbo)
void KRMeshManager::KRVBOData::init(KRMeshManager *manager, KRDataBlock &data, KRDataBlock &index_data, int vertex_attrib_flags, bool static_vbo, vbo_type t)
{
m_manager = manager;
m_temp_vbo = temp_vbo;
m_type = t;
m_static_vbo = static_vbo;
m_data = &data;
m_index_data = &index_data;
@@ -528,14 +587,12 @@ void KRMeshManager::KRVBOData::init(KRMeshManager *manager, KRDataBlock &data, K
KRMeshManager::KRVBOData::~KRVBOData()
{
unload();
}
void KRMeshManager::KRVBOData::load()
{
if(isLoaded()) {
if(isVBOLoaded()) {
return;
}
m_vao_handle = -1;
@@ -586,6 +643,11 @@ void KRMeshManager::KRVBOData::load()
m_index_data->unlock();
#endif
}
m_is_vbo_loaded = true;
if(m_type == CONSTANT) {
m_is_vbo_ready = true;
}
}
void KRMeshManager::KRVBOData::unload()
@@ -605,6 +667,9 @@ void KRMeshManager::KRVBOData::unload()
GLDEBUG(glDeleteBuffers(1, &m_vbo_handle_indexes));
m_vbo_handle_indexes = -1;
}
m_is_vbo_loaded = false;
m_is_vbo_ready = false;
}
void KRMeshManager::KRVBOData::bind()
@@ -628,6 +693,31 @@ void KRMeshManager::KRVBOData::resetPoolExpiry(float lodCoverage)
if(current_frame != m_last_frame_used) {
m_last_frame_used = current_frame;
m_last_frame_max_lod_coverage = 0.0f;
m_manager->primeVBO(this);
}
m_last_frame_max_lod_coverage = KRMAX(lodCoverage, m_last_frame_max_lod_coverage);
}
}
float KRMeshManager::KRVBOData::getStreamPriority()
{
long current_frame = m_manager->getContext().getCurrentFrame();
if(current_frame > m_last_frame_used + 5) {
return 1.0f - KRCLAMP((float)(current_frame - m_last_frame_used) / 60.0f, 0.0f, 1.0f);
} else {
return 10000.0f + m_last_frame_max_lod_coverage * 10.0f;
}
}
void KRMeshManager::KRVBOData::_swapHandles()
{
m_is_vbo_ready = m_is_vbo_loaded;
}
void KRMeshManager::primeVBO(KRVBOData *vbo_data)
{
if(m_vbosActive.find(vbo_data->m_data) == m_vbosActive.end()) {
m_vbosActive[vbo_data->m_data] = vbo_data;
}
}

View File

@@ -48,9 +48,9 @@ public:
KRMeshManager(KRContext &context);
virtual ~KRMeshManager();
void rotateBuffers(bool new_frame);
void startFrame(float deltaTime);
void endFrame(float deltaTime);
void firstFrame();
KRMesh *loadModel(const char *szName, KRDataBlock *pData);
std::vector<KRMesh *> getModel(const char *szName);
@@ -63,16 +63,23 @@ public:
public:
typedef enum {
STREAMING,
CONSTANT,
TEMPORARY
} vbo_type;
KRVBOData();
KRVBOData(KRMeshManager *manager, KRDataBlock &data, KRDataBlock &index_data, int vertex_attrib_flags, bool static_vbo, bool temp_vbo);
void init(KRMeshManager *manager, KRDataBlock &data, KRDataBlock &index_data, int vertex_attrib_flags, bool static_vbo, bool temp_vbo);
KRVBOData(KRMeshManager *manager, KRDataBlock &data, KRDataBlock &index_data, int vertex_attrib_flags, bool static_vbo, vbo_type t);
void init(KRMeshManager *manager, KRDataBlock &data, KRDataBlock &index_data, int vertex_attrib_flags, bool static_vbo, vbo_type t);
~KRVBOData();
KRDataBlock *m_data;
KRDataBlock *m_index_data;
bool isLoaded() { return m_vbo_handle != -1; }
bool isVBOLoaded() { return m_is_vbo_loaded; }
bool isVBOReady() { return m_is_vbo_ready; }
void load();
void unload();
void bind();
@@ -81,10 +88,16 @@ public:
KRVBOData(const KRVBOData& o) = delete;
KRVBOData(KRVBOData& o) = delete;
bool isTemporary() { return m_temp_vbo; }
bool getSize() { return m_size; }
void resetPoolExpiry(float lodCoverage);
long getLastFrameUsed() { return m_last_frame_used; }
vbo_type getType() { return m_type; }
float getStreamPriority();
void _swapHandles();
private:
KRMeshManager *m_manager;
@@ -92,17 +105,18 @@ public:
GLuint m_vbo_handle;
GLuint m_vbo_handle_indexes;
GLuint m_vao_handle;
bool m_static_vbo;
bool m_temp_vbo;
GLsizeiptr m_size;
long m_last_frame_used;
float m_last_frame_max_lod_coverage;
vbo_type m_type;
bool m_static_vbo;
bool m_is_vbo_loaded;
bool m_is_vbo_ready;
};
void bindVBO(KRVBOData *vbo_data);
void bindVBO(KRDataBlock &data, KRDataBlock &index_data, int vertex_attrib_flags, bool static_vbo);
void releaseVBO(KRDataBlock &data);
void bindVBO(KRVBOData *vbo_data, float lodCoverage);
void bindVBO(KRDataBlock &data, KRDataBlock &index_data, int vertex_attrib_flags, bool static_vbo, float lodCoverage);
void unbindVBO();
long getMemUsed();
long getMemActive();
@@ -137,7 +151,6 @@ public:
long getMemoryTransferedThisFrame();
int getActiveVBOCount();
int getPoolVBOCount();
struct draw_call_info {
KRNode::RenderPass pass;
@@ -168,7 +181,8 @@ private:
KRVBOData *m_currentVBO;
unordered_map<KRDataBlock *, KRVBOData *> m_vbosActive;
unordered_map<KRDataBlock *, KRVBOData *> m_vbosPool;
std::vector<std::pair<float, KRVBOData *> > m_activeVBOs_streamer;
std::vector<std::pair<float, KRVBOData *> > m_activeVBOs_streamer_copy;
KRDataBlock m_randomParticleVertexData;
KRDataBlock m_volumetricLightingVertexData;
@@ -178,6 +192,15 @@ private:
std::vector<draw_call_info> m_draw_calls;
bool m_draw_call_logging_enabled;
bool m_draw_call_log_used;
bool m_first_frame;
std::mutex m_streamerFenceMutex;
bool m_streamerComplete;
void balanceVBOMemory(long &memoryRemaining, long &memoryRemainingThisFrame);
void primeVBO(KRVBOData *vbo_data);
};

View File

@@ -34,6 +34,8 @@
KRMeshQuad::KRMeshQuad(KRContext &context) : KRMesh(context, "__quad")
{
m_constant = true;
KRMesh::mesh_info mi;
mi.vertices.push_back(KRVector3(-1.0f, -1.0f, 0.0f));
@@ -52,7 +54,6 @@ KRMeshQuad::KRMeshQuad(KRContext &context) : KRMesh(context, "__quad")
mi.material_names.push_back("");
mi.format = KRENGINE_MODEL_FORMAT_STRIP;
LoadData(mi, true, true);
}

View File

@@ -34,6 +34,8 @@
KRMeshSphere::KRMeshSphere(KRContext &context) : KRMesh(context, "__sphere")
{
m_constant = true;
KRMesh::mesh_info mi;
// Create a triangular facet approximation to a sphere

View File

@@ -80,7 +80,7 @@ void KRParticleSystemNewtonian::render(KRCamera *pCamera, std::vector<KRPointLig
pParticleShader->setUniform(KRShader::KRENGINE_UNIFORM_FLARE_SIZE, 1.0f);
KRDataBlock index_data;
m_pContext->getMeshManager()->bindVBO(m_pContext->getMeshManager()->getRandomParticles(), index_data, (1 << KRMesh::KRENGINE_ATTRIB_VERTEX) | (1 << KRMesh::KRENGINE_ATTRIB_TEXUVA), false);
m_pContext->getMeshManager()->bindVBO(m_pContext->getMeshManager()->getRandomParticles(), index_data, (1 << KRMesh::KRENGINE_ATTRIB_VERTEX) | (1 << KRMesh::KRENGINE_ATTRIB_TEXUVA), false, 1.0f);
GLDEBUG(glDrawArrays(GL_TRIANGLES, 0, particle_count*3));
}
}

View File

@@ -97,7 +97,7 @@ void KRPointLight::render(KRCamera *pCamera, std::vector<KRPointLight *> &point_
GLDEBUG(glDisable(GL_DEPTH_TEST));
// Render a full screen quad
m_pContext->getMeshManager()->bindVBO(&m_pContext->getMeshManager()->KRENGINE_VBO_DATA_2D_SQUARE_VERTICES);
m_pContext->getMeshManager()->bindVBO(&m_pContext->getMeshManager()->KRENGINE_VBO_DATA_2D_SQUARE_VERTICES, 1.0f);
GLDEBUG(glDrawArrays(GL_TRIANGLE_STRIP, 0, 4));
} else {
#if GL_OES_vertex_array_object

View File

@@ -115,7 +115,7 @@ void KRReverbZone::render(KRCamera *pCamera, std::vector<KRPointLight *> &point_
std::vector<KRMesh *> sphereModels = getContext().getMeshManager()->getModel("__sphere");
if(sphereModels.size()) {
for(int i=0; i < sphereModels[0]->getSubmeshCount(); i++) {
sphereModels[0]->renderSubmesh(i, renderPass, getName(), "visualize_overlay");
sphereModels[0]->renderSubmesh(i, renderPass, getName(), "visualize_overlay", 1.0f);
}
}

View File

@@ -281,7 +281,7 @@ void KRScene::render(KROctreeNode *pOctreeNode, unordered_map<KRAABB, int> &visi
KRMat4 mvpmatrix = matModel * viewport.getViewProjectionMatrix();
getContext().getMeshManager()->bindVBO(&getContext().getMeshManager()->KRENGINE_VBO_DATA_3D_CUBE_VERTICES);
getContext().getMeshManager()->bindVBO(&getContext().getMeshManager()->KRENGINE_VBO_DATA_3D_CUBE_VERTICES, 1.0f);
// Enable additive blending
if(renderPass != KRNode::RENDER_PASS_FORWARD_TRANSPARENT && renderPass != KRNode::RENDER_PASS_ADDITIVE_PARTICLES && renderPass != KRNode::RENDER_PASS_VOLUMETRIC_EFFECTS_ADDITIVE) {

View File

@@ -121,7 +121,7 @@ void KRSprite::render(KRCamera *pCamera, std::vector<KRPointLight *> &point_ligh
if(getContext().getShaderManager()->selectShader(*pCamera, pShader, viewport, getModelMatrix(), point_lights, directional_lights, spot_lights, 0, renderPass, rim_color, 0.0f)) {
pShader->setUniform(KRShader::KRENGINE_UNIFORM_MATERIAL_ALPHA, m_spriteAlpha);
m_pContext->getTextureManager()->selectTexture(0, m_pSpriteTexture, 0.0f, KRTexture::TEXTURE_USAGE_SPRITE);
m_pContext->getMeshManager()->bindVBO(&m_pContext->getMeshManager()->KRENGINE_VBO_DATA_2D_SQUARE_VERTICES);
m_pContext->getMeshManager()->bindVBO(&m_pContext->getMeshManager()->KRENGINE_VBO_DATA_2D_SQUARE_VERTICES, 1.0f);
GLDEBUG(glDrawArrays(GL_TRIANGLE_STRIP, 0, 4));
}
}

View File

@@ -256,7 +256,6 @@ void KRTextureManager::startFrame(float deltaTime)
const long KRENGINE_TEXTURE_EXPIRY_FRAMES = 10;
std::set<KRTexture *> expiredTextures;
for(std::set<KRTexture *>::iterator itr=m_activeTextures.begin(); itr != m_activeTextures.end(); itr++) {
KRTexture *activeTexture = *itr;
@@ -282,7 +281,6 @@ void KRTextureManager::startFrame(float deltaTime)
m_streamerFenceMutex.unlock();
m_memoryTransferredThisFrame = 0;
rotateBuffers();
}
void KRTextureManager::endFrame(float deltaTime)
@@ -400,11 +398,6 @@ void KRTextureManager::balanceTextureMemory(long &memoryRemaining, long &memoryR
}
void KRTextureManager::rotateBuffers()
{
}
long KRTextureManager::getMemoryTransferedThisFrame()
{
return m_memoryTransferredThisFrame;

View File

@@ -101,7 +101,6 @@ private:
std::atomic<long> m_textureMemUsed;
void rotateBuffers();
void balanceTextureMemory(long &memoryRemaining, long &memoryRemainingThisFrame);
std::mutex m_streamerFenceMutex;