Refactoring of streamer code to integrate texture and vbo memory management in progress.
This commit is contained in:
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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,6 +253,10 @@ 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) {
|
||||
if(getStreamLevel() == kraken_stream_level::STREAM_LEVEL_OUT) {
|
||||
preStream(lod_coverage);
|
||||
} else {
|
||||
|
||||
getSubmeshes();
|
||||
getMaterials();
|
||||
|
||||
@@ -225,7 +269,7 @@ void KRMesh::render(const std::string &object_name, KRCamera *pCamera, std::vect
|
||||
|
||||
if(!pMaterial->isTransparent()) {
|
||||
// Exclude transparent and semi-transparent meshes from shadow maps
|
||||
renderSubmesh(iSubmesh, renderPass, object_name, pMaterial->getName());
|
||||
renderSubmesh(iSubmesh, renderPass, object_name, pMaterial->getName(), lod_coverage);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -247,24 +291,23 @@ void KRMesh::render(const std::string &object_name, KRCamera *pCamera, std::vect
|
||||
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());
|
||||
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());
|
||||
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());
|
||||
renderSubmesh(iSubmesh, renderPass, object_name, pMaterial->getName(), lod_coverage);
|
||||
|
||||
// Render front faces second
|
||||
GLDEBUG(glCullFace(GL_BACK));
|
||||
renderSubmesh(iSubmesh, renderPass, object_name, pMaterial->getName());
|
||||
renderSubmesh(iSubmesh, renderPass, object_name, pMaterial->getName(), lod_coverage);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -303,22 +346,23 @@ 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();
|
||||
getSubmeshes();
|
||||
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;
|
||||
// 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,27 +373,19 @@ 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);
|
||||
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);
|
||||
} else {
|
||||
vbo_data_block = m_submeshes[iSubmesh]->vbo_data_blocks[vbo_index];
|
||||
}
|
||||
vbo_index++;
|
||||
|
||||
m_pContext->getMeshManager()->bindVBO(vbo_data_block);
|
||||
|
||||
|
||||
int vertex_draw_count = cVertexes;
|
||||
if(vertex_draw_count > index_count - index_group_offset) vertex_draw_count = index_count - index_group_offset;
|
||||
|
||||
glDrawElements(GL_TRIANGLES, vertex_draw_count, GL_UNSIGNED_SHORT, BUFFER_OFFSET(index_group_offset * 2));
|
||||
m_pContext->getMeshManager()->log_draw_call(renderPass, object_name, material_name, vertex_draw_count);
|
||||
cVertexes -= vertex_draw_count;
|
||||
index_group_offset = 0;
|
||||
}
|
||||
@@ -363,20 +399,74 @@ void KRMesh::renderSubmesh(int iSubmesh, KRNode::RenderPass renderPass, const st
|
||||
GLsizei cBufferVertexes = iBuffer < cBuffers - 1 ? MAX_VBO_SIZE : vertex_count % MAX_VBO_SIZE;
|
||||
int vertex_size = m_vertex_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);
|
||||
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);
|
||||
} else {
|
||||
vbo_data_block = m_submeshes[iSubmesh]->vbo_data_blocks[vbo_index];
|
||||
}
|
||||
vbo_index++;
|
||||
|
||||
m_pContext->getMeshManager()->bindVBO(vbo_data_block);
|
||||
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;
|
||||
|
||||
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);
|
||||
|
||||
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);
|
||||
|
||||
|
||||
int vertex_draw_count = cVertexes;
|
||||
if(vertex_draw_count > index_count - index_group_offset) vertex_draw_count = index_count - index_group_offset;
|
||||
|
||||
glDrawElements(GL_TRIANGLES, vertex_draw_count, GL_UNSIGNED_SHORT, BUFFER_OFFSET(index_group_offset * 2));
|
||||
m_pContext->getMeshManager()->log_draw_call(renderPass, object_name, material_name, vertex_draw_count);
|
||||
cVertexes -= vertex_draw_count;
|
||||
index_group_offset = 0;
|
||||
}
|
||||
|
||||
} else {
|
||||
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 : cVertexes % MAX_VBO_SIZE;
|
||||
|
||||
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) {
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -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));
|
||||
|
||||
@@ -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();
|
||||
|
||||
switch(vbo_to_release->getType()) {
|
||||
case KRVBOData::STREAMING:
|
||||
vbo_to_release->unload();
|
||||
if(vbo_to_release->isTemporary()) {
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
@@ -179,6 +193,15 @@ private:
|
||||
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);
|
||||
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -101,7 +101,6 @@ private:
|
||||
|
||||
std::atomic<long> m_textureMemUsed;
|
||||
|
||||
void rotateBuffers();
|
||||
void balanceTextureMemory(long &memoryRemaining, long &memoryRemainingThisFrame);
|
||||
|
||||
std::mutex m_streamerFenceMutex;
|
||||
|
||||
Reference in New Issue
Block a user