2011-10-25 05:03:10 +00:00
//
2013-01-09 22:37:23 +00:00
// KRMeshManager.cpp
2021-08-16 16:35:36 -07:00
// Kraken Engine
2011-10-25 05:03:10 +00:00
//
2022-04-03 21:56:23 -07:00
// Copyright 2022 Kearwood Gilbert. All rights reserved.
2011-10-25 06:16:47 +00:00
//
// Redistribution and use in source and binary forms, with or without modification, are
// permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice, this list of
// conditions and the following disclaimer.
2013-03-21 17:32:26 -07:00
//
2011-10-25 06:16:47 +00:00
// 2. Redistributions in binary form must reproduce the above copyright notice, this list
// of conditions and the following disclaimer in the documentation and/or other materials
// provided with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY KEARWOOD GILBERT ''AS IS'' AND ANY EXPRESS OR IMPLIED
// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL KEARWOOD GILBERT OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// The views and conclusions contained in the software and documentation are those of the
// authors and should not be interpreted as representing official policies, either expressed
// or implied, of Kearwood Gilbert.
2011-10-25 05:03:10 +00:00
//
2013-01-11 03:21:19 +00:00
# include "KREngine-common.h"
2013-01-09 22:37:23 +00:00
# include "KRMeshManager.h"
2011-10-25 05:03:10 +00:00
2013-01-11 03:21:19 +00:00
# include "KRMesh.h"
# include "KRMeshCube.h"
2013-11-30 12:46:01 -08:00
# include "KRMeshQuad.h"
2013-01-11 03:21:19 +00:00
# include "KRMeshSphere.h"
2012-04-12 19:43:08 +00:00
2022-01-21 23:32:00 -08:00
KRMeshManager : : KRMeshManager ( KRContext & context )
: KRResourceManager ( context )
, m_currentVBO ( NULL )
, m_vboMemUsed ( 0 )
, m_memoryTransferredThisFrame ( 0 )
, m_streamerComplete ( true )
, m_draw_call_logging_enabled ( false )
, m_draw_call_log_used ( false )
{
}
void KRMeshManager : : init ( ) {
addModel ( new KRMeshCube ( * m_pContext ) ) ;
addModel ( new KRMeshQuad ( * m_pContext ) ) ;
addModel ( new KRMeshSphere ( * m_pContext ) ) ;
2013-11-09 16:08:08 -08:00
// ---- Initialize stock models ----
2022-04-03 23:54:10 -07:00
static const float _KRENGINE_VBO_3D_CUBE_VERTEX_DATA [ ] = {
2013-11-09 16:08:08 -08:00
1.0 , 1.0 , 1.0 ,
- 1.0 , 1.0 , 1.0 ,
1.0 , - 1.0 , 1.0 ,
- 1.0 , - 1.0 , 1.0 ,
- 1.0 , - 1.0 , - 1.0 ,
- 1.0 , 1.0 , 1.0 ,
- 1.0 , 1.0 , - 1.0 ,
1.0 , 1.0 , 1.0 ,
1.0 , 1.0 , - 1.0 ,
1.0 , - 1.0 , 1.0 ,
1.0 , - 1.0 , - 1.0 ,
- 1.0 , - 1.0 , - 1.0 ,
1.0 , 1.0 , - 1.0 ,
- 1.0 , 1.0 , - 1.0
} ;
KRENGINE_VBO_3D_CUBE_ATTRIBS = ( 1 < < KRMesh : : KRENGINE_ATTRIB_VERTEX ) ;
2022-04-03 23:54:10 -07:00
KRENGINE_VBO_3D_CUBE_VERTICES . expand ( sizeof ( float ) * 3 * 14 ) ;
2013-11-09 16:08:08 -08:00
KRENGINE_VBO_3D_CUBE_VERTICES . lock ( ) ;
2022-04-03 23:54:10 -07:00
memcpy ( KRENGINE_VBO_3D_CUBE_VERTICES . getStart ( ) , _KRENGINE_VBO_3D_CUBE_VERTEX_DATA , sizeof ( float ) * 3 * 14 ) ;
2013-11-09 16:08:08 -08:00
KRENGINE_VBO_3D_CUBE_VERTICES . unlock ( ) ;
2022-02-07 23:38:57 -08:00
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
# if KRENGINE_DEBUG_GPU_LABELS
, " Cube Mesh [built-in] "
# endif
) ;
2014-05-15 23:33:01 -07:00
2022-04-03 23:54:10 -07:00
static const float _KRENGINE_VBO_2D_SQUARE_VERTEX_DATA [ ] = {
2013-11-09 16:08:08 -08:00
- 1.0f , - 1.0f , 0.0f , 0.0f , 0.0f ,
1.0f , - 1.0f , 0.0f , 1.0f , 0.0f ,
- 1.0f , 1.0f , 0.0f , 0.0f , 1.0f ,
1.0f , 1.0f , 0.0f , 1.0f , 1.0f
} ;
KRENGINE_VBO_2D_SQUARE_ATTRIBS = ( 1 < < KRMesh : : KRENGINE_ATTRIB_VERTEX ) | ( 1 < < KRMesh : : KRENGINE_ATTRIB_TEXUVA ) ;
2022-04-03 23:54:10 -07:00
KRENGINE_VBO_2D_SQUARE_VERTICES . expand ( sizeof ( float ) * 5 * 4 ) ;
2013-11-09 16:08:08 -08:00
KRENGINE_VBO_2D_SQUARE_VERTICES . lock ( ) ;
2022-04-03 23:54:10 -07:00
memcpy ( KRENGINE_VBO_2D_SQUARE_VERTICES . getStart ( ) , _KRENGINE_VBO_2D_SQUARE_VERTEX_DATA , sizeof ( float ) * 5 * 4 ) ;
2013-11-09 16:08:08 -08:00
KRENGINE_VBO_2D_SQUARE_VERTICES . unlock ( ) ;
2014-05-15 23:33:01 -07:00
2022-02-07 23:38:57 -08:00
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
# if KRENGINE_DEBUG_GPU_LABELS
, " Square Mesh [built-in] "
# endif
) ;
2014-05-15 23:33:01 -07:00
2011-10-25 05:03:10 +00:00
}
2013-01-09 22:37:23 +00:00
KRMeshManager : : ~ KRMeshManager ( ) {
2013-04-25 17:23:36 -07:00
for ( unordered_multimap < std : : string , KRMesh * > : : iterator itr = m_models . begin ( ) ; itr ! = m_models . end ( ) ; + + itr ) {
2011-10-25 05:03:10 +00:00
delete ( * itr ) . second ;
}
2020-07-22 17:37:22 -07:00
m_models . clear ( ) ;
2011-10-25 05:03:10 +00:00
}
2019-12-08 16:29:49 -08:00
KRResource * KRMeshManager : : loadResource ( const std : : string & name , const std : : string & extension , KRDataBlock * data )
{
if ( extension . compare ( " krmesh " ) = = 0 ) {
return loadModel ( name . c_str ( ) , data ) ;
}
return nullptr ;
}
KRResource * KRMeshManager : : getResource ( const std : : string & name , const std : : string & extension )
{
if ( extension . compare ( " krmesh " ) = = 0 ) {
std : : string lodBaseName ;
int lodCoverage ;
KRMesh : : parseName ( name , lodBaseName , lodCoverage ) ;
std : : vector < KRMesh * > models = getModel ( lodBaseName . c_str ( ) ) ;
for ( KRMesh * mesh : models ) {
if ( mesh - > getLODCoverage ( ) = = lodCoverage ) {
return mesh ;
}
}
}
return nullptr ;
}
2013-01-09 22:37:23 +00:00
KRMesh * KRMeshManager : : loadModel ( const char * szName , KRDataBlock * pData ) {
2013-04-04 16:09:29 -07:00
KRMesh * pModel = new KRMesh ( * m_pContext , szName , pData ) ;
2012-12-14 20:45:16 +00:00
addModel ( pModel ) ;
2011-10-25 05:03:10 +00:00
return pModel ;
}
2013-01-09 22:37:23 +00:00
void KRMeshManager : : addModel ( KRMesh * model ) {
2013-04-04 16:09:29 -07:00
std : : string lowerName = model - > getLODBaseName ( ) ;
std : : transform ( lowerName . begin ( ) , lowerName . end ( ) ,
lowerName . begin ( ) , : : tolower ) ;
m_models . insert ( std : : pair < std : : string , KRMesh * > ( lowerName , model ) ) ;
2012-12-14 20:45:16 +00:00
}
2022-07-06 23:42:47 -07:00
KRMesh * KRMeshManager : : getMaxLODModel ( const char * szName ) {
std : : vector < KRMesh * > models = getModel ( szName ) ;
// models are always in order of highest LOD first
if ( models . size ( ) ) {
return models [ 0 ] ;
}
return nullptr ;
}
2013-01-09 22:37:23 +00:00
std : : vector < KRMesh * > KRMeshManager : : getModel ( const char * szName ) {
2012-10-05 02:23:00 +00:00
std : : string lowerName = szName ;
std : : transform ( lowerName . begin ( ) , lowerName . end ( ) ,
lowerName . begin ( ) , : : tolower ) ;
2013-01-09 22:37:23 +00:00
std : : vector < KRMesh * > matching_models ;
2012-10-05 02:23:00 +00:00
2013-04-25 17:23:36 -07:00
std : : pair < unordered_multimap < std : : string , KRMesh * > : : iterator , unordered_multimap < std : : string , KRMesh * > : : iterator > range = m_models . equal_range ( lowerName ) ;
for ( unordered_multimap < std : : string , KRMesh * > : : iterator itr_match = range . first ; itr_match ! = range . second ; itr_match + + ) {
2012-10-05 02:23:00 +00:00
matching_models . push_back ( itr_match - > second ) ;
2012-09-13 20:09:19 +00:00
}
2012-10-05 02:23:00 +00:00
2013-01-09 22:37:23 +00:00
std : : sort ( matching_models . begin ( ) , matching_models . end ( ) , KRMesh : : lod_sort_predicate ) ;
2012-10-05 02:23:00 +00:00
2012-12-14 20:45:16 +00:00
if ( matching_models . size ( ) = = 0 ) {
2013-12-14 16:06:44 -08:00
KRContext : : Log ( KRContext : : LOG_LEVEL_INFORMATION , " Model not found: %s " , lowerName . c_str ( ) ) ;
2012-10-05 02:23:00 +00:00
}
return matching_models ;
2011-10-25 05:03:10 +00:00
}
2013-04-25 17:23:36 -07:00
unordered_multimap < std : : string , KRMesh * > & KRMeshManager : : getModels ( ) {
2012-04-05 21:18:25 +00:00
return m_models ;
}
2022-02-28 20:14:22 -08:00
void KRMeshManager : : bindVBO ( VkCommandBuffer & commandBuffer , KRVBOData * vbo_data , float lodCoverage )
2014-05-13 23:49:03 -07:00
{
2014-05-27 22:51:52 -07:00
vbo_data - > resetPoolExpiry ( lodCoverage ) ;
2014-05-13 23:49:03 -07:00
bool vbo_changed = false ;
if ( m_currentVBO = = NULL ) {
vbo_changed = true ;
2014-05-15 23:33:01 -07:00
} else if ( m_currentVBO - > m_data ! = vbo_data - > m_data ) {
2014-05-13 23:49:03 -07:00
vbo_changed = true ;
}
2014-05-15 23:33:01 -07:00
bool used_vbo_data = false ;
2014-05-13 23:49:03 -07:00
if ( vbo_changed ) {
2012-09-11 03:06:35 +00:00
2014-05-15 23:33:01 -07:00
if ( m_vbosActive . find ( vbo_data - > m_data ) ! = m_vbosActive . end ( ) ) {
m_currentVBO = m_vbosActive [ vbo_data - > m_data ] ;
2012-09-11 03:06:35 +00:00
} else {
2014-05-15 23:33:01 -07:00
used_vbo_data = true ;
m_currentVBO = vbo_data ;
2012-09-11 04:32:04 +00:00
2014-05-15 23:33:01 -07:00
m_vbosActive [ vbo_data - > m_data ] = m_currentVBO ;
2012-09-11 03:06:35 +00:00
}
2014-05-27 22:51:52 -07:00
2022-02-28 20:14:22 -08:00
m_currentVBO - > bind ( commandBuffer ) ;
2012-09-11 03:06:35 +00:00
}
2014-05-15 23:33:01 -07:00
2014-05-27 22:51:52 -07:00
if ( ! used_vbo_data & & vbo_data - > getType ( ) = = KRVBOData : : TEMPORARY ) {
2014-05-15 23:33:01 -07:00
delete vbo_data ;
}
}
2014-05-27 22:51:52 -07:00
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 ( ) ;
2022-01-21 23:32:00 -08:00
2014-05-27 22:51:52 -07:00
// 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
2014-06-01 15:34:31 -07:00
const long KRENGINE_VBO_EXPIRY_FRAMES = 1 ;
2014-05-27 22:51:52 -07:00
std : : set < KRVBOData * > expiredVBOs ;
for ( auto itr = m_vbosActive . begin ( ) ; itr ! = m_vbosActive . end ( ) ; itr + + ) {
KRVBOData * activeVBO = ( * itr ) . second ;
activeVBO - > _swapHandles ( ) ;
2022-01-21 23:32:00 -08:00
if ( activeVBO - > getType ( ) = = KRVBOData : : CONSTANT ) {
// Ensure that CONSTANT data is always loaded
float priority = std : : numeric_limits < float > : : max ( ) ;
m_activeVBOs_streamer_copy . push_back ( std : : pair < float , KRVBOData * > ( priority , activeVBO ) ) ;
} else if ( activeVBO - > getLastFrameUsed ( ) + KRENGINE_VBO_EXPIRY_FRAMES < getContext ( ) . getCurrentFrame ( ) ) {
2014-05-27 22:51:52 -07:00
// Expire VBO's that haven't been used in a long time
switch ( activeVBO - > getType ( ) ) {
case KRVBOData : : STREAMING :
activeVBO - > unload ( ) ;
break ;
case KRVBOData : : TEMPORARY :
delete activeVBO ;
break ;
case KRVBOData : : CONSTANT :
// CONSTANT VBO's are not unloaded
break ;
}
expiredVBOs . insert ( activeVBO ) ;
2022-01-21 23:32:00 -08:00
} else if ( activeVBO - > getType ( ) = = KRVBOData : : STREAMING ) {
float priority = activeVBO - > getStreamPriority ( ) ;
m_activeVBOs_streamer_copy . push_back ( std : : pair < float , KRVBOData * > ( priority , activeVBO ) ) ;
2014-05-27 22:51:52 -07:00
}
}
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 : : doStreaming ( long & memoryRemaining , long & memoryRemainingThisFrame )
2014-05-15 23:33:01 -07:00
{
2014-05-27 22:51:52 -07:00
// 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 ( ) ;
2014-08-27 22:06:09 -07:00
} else {
memoryRemaining - = getMemUsed ( ) ;
2014-05-27 22:51:52 -07:00
}
}
void KRMeshManager : : balanceVBOMemory ( long & memoryRemaining , long & memoryRemainingThisFrame )
{
std : : sort ( m_activeVBOs_streamer . begin ( ) , m_activeVBOs_streamer . end ( ) , std : : greater < std : : pair < float , KRVBOData * > > ( ) ) ;
2014-08-27 02:24:49 -07:00
for ( auto vbo_itr = m_activeVBOs_streamer . begin ( ) ; vbo_itr ! = m_activeVBOs_streamer . end ( ) ; vbo_itr + + ) {
2014-05-27 22:51:52 -07:00
KRVBOData * vbo_data = ( * vbo_itr ) . second ;
2014-08-27 02:24:49 -07:00
long vbo_size = vbo_data - > getSize ( ) ;
2014-05-27 22:51:52 -07:00
if ( ! vbo_data - > isVBOLoaded ( ) ) {
if ( memoryRemainingThisFrame > vbo_size ) {
vbo_data - > load ( ) ;
memoryRemainingThisFrame - = vbo_size ;
}
}
2014-08-27 02:24:49 -07:00
memoryRemaining - = vbo_size ;
2014-05-27 22:51:52 -07:00
}
}
2022-02-28 20:14:22 -08:00
void KRMeshManager : : bindVBO ( VkCommandBuffer & commandBuffer , KRDataBlock & data , KRDataBlock & index_data , int vertex_attrib_flags , bool static_vbo , float lodCoverage
2022-02-07 23:38:57 -08:00
# if KRENGINE_DEBUG_GPU_LABELS
, const char * debug_label
# endif
)
2014-05-27 22:51:52 -07:00
{
2022-02-07 23:38:57 -08:00
KRVBOData * vbo_data = new KRVBOData ( this , data , index_data , vertex_attrib_flags , static_vbo , KRVBOData : : TEMPORARY
# if KRENGINE_DEBUG_GPU_LABELS
, debug_label
# endif
) ;
2014-05-27 22:51:52 -07:00
vbo_data - > load ( ) ;
2022-02-28 20:14:22 -08:00
bindVBO ( commandBuffer , vbo_data , lodCoverage ) ;
2012-09-11 03:06:35 +00:00
}
2013-01-09 22:37:23 +00:00
long KRMeshManager : : getMemUsed ( )
2012-09-11 04:32:04 +00:00
{
return m_vboMemUsed ;
}
2012-09-13 20:09:19 +00:00
2013-03-21 17:32:26 -07:00
long KRMeshManager : : getMemActive ( )
{
long mem_active = 0 ;
2014-05-13 23:49:03 -07:00
for ( unordered_map < KRDataBlock * , KRVBOData * > : : iterator itr = m_vbosActive . begin ( ) ; itr ! = m_vbosActive . end ( ) ; itr + + ) {
2014-05-15 23:33:01 -07:00
mem_active + = ( * itr ) . second - > getSize ( ) ;
2013-03-21 17:32:26 -07:00
}
return mem_active ;
}
2013-11-09 16:08:08 -08:00
KRDataBlock & KRMeshManager : : getVolumetricLightingVertexes ( )
2012-11-09 09:18:38 +00:00
{
2013-11-09 16:08:08 -08:00
if ( m_volumetricLightingVertexData . getSize ( ) = = 0 ) {
m_volumetricLightingVertexData . expand ( sizeof ( VolumetricLightingVertexData ) * KRENGINE_MAX_VOLUMETRIC_PLANES * 6 ) ;
m_volumetricLightingVertexData . lock ( ) ;
VolumetricLightingVertexData * vertex_data = ( VolumetricLightingVertexData * ) m_volumetricLightingVertexData . getStart ( ) ;
2012-11-09 09:18:38 +00:00
int iVertex = 0 ;
2012-11-23 01:02:22 +00:00
for ( int iPlane = 0 ; iPlane < KRENGINE_MAX_VOLUMETRIC_PLANES ; iPlane + + ) {
2013-11-09 16:08:08 -08:00
vertex_data [ iVertex ] . vertex . x = - 1.0f ;
vertex_data [ iVertex ] . vertex . y = - 1.0f ;
2022-04-03 23:54:10 -07:00
vertex_data [ iVertex ] . vertex . z = ( float ) iPlane ;
2012-11-09 09:18:38 +00:00
iVertex + + ;
2013-11-09 16:08:08 -08:00
vertex_data [ iVertex ] . vertex . x = 1.0f ;
vertex_data [ iVertex ] . vertex . y = - 1.0f ;
2022-04-03 23:54:10 -07:00
vertex_data [ iVertex ] . vertex . z = ( float ) iPlane ;
2012-11-09 09:18:38 +00:00
iVertex + + ;
2013-11-09 16:08:08 -08:00
vertex_data [ iVertex ] . vertex . x = - 1.0f ;
vertex_data [ iVertex ] . vertex . y = 1.0f ;
2022-04-03 23:54:10 -07:00
vertex_data [ iVertex ] . vertex . z = ( float ) iPlane ;
2012-11-09 09:18:38 +00:00
iVertex + + ;
2013-11-09 16:08:08 -08:00
vertex_data [ iVertex ] . vertex . x = - 1.0f ;
vertex_data [ iVertex ] . vertex . y = 1.0f ;
2022-04-03 23:54:10 -07:00
vertex_data [ iVertex ] . vertex . z = ( float ) iPlane ;
2012-11-09 09:18:38 +00:00
iVertex + + ;
2013-11-09 16:08:08 -08:00
vertex_data [ iVertex ] . vertex . x = 1.0f ;
vertex_data [ iVertex ] . vertex . y = - 1.0f ;
2022-04-03 23:54:10 -07:00
vertex_data [ iVertex ] . vertex . z = ( float ) iPlane ;
2012-11-09 09:18:38 +00:00
iVertex + + ;
2013-11-09 16:08:08 -08:00
vertex_data [ iVertex ] . vertex . x = 1.0f ;
vertex_data [ iVertex ] . vertex . y = 1.0f ;
2022-04-03 23:54:10 -07:00
vertex_data [ iVertex ] . vertex . z = ( float ) iPlane ;
2012-11-09 09:18:38 +00:00
iVertex + + ;
2013-11-09 16:08:08 -08:00
2012-11-09 09:18:38 +00:00
}
2013-11-09 16:08:08 -08:00
m_volumetricLightingVertexData . unlock ( ) ;
2012-11-09 09:18:38 +00:00
}
return m_volumetricLightingVertexData ;
}
2013-11-09 16:08:08 -08:00
KRDataBlock & KRMeshManager : : getRandomParticles ( )
2012-11-02 20:50:45 +00:00
{
2013-11-09 16:08:08 -08:00
if ( m_randomParticleVertexData . getSize ( ) = = 0 ) {
m_randomParticleVertexData . expand ( sizeof ( RandomParticleVertexData ) * KRENGINE_MAX_RANDOM_PARTICLES * 3 ) ;
m_randomParticleVertexData . lock ( ) ;
RandomParticleVertexData * vertex_data = ( RandomParticleVertexData * ) m_randomParticleVertexData . getStart ( ) ;
2012-11-23 01:02:22 +00:00
// Generate vertices for randomly placed equilateral triangles with a side length of 1 and an origin point centered so that an inscribed circle can be efficiently rendered without wasting fill
2013-04-24 12:48:55 -07:00
float equilateral_triangle_height = sqrt ( 3.0f ) * 0.5f ;
2012-11-23 01:02:22 +00:00
float inscribed_circle_radius = 1.0f / ( 2.0f * sqrt ( 3.0f ) ) ;
2012-11-02 20:50:45 +00:00
int iVertex = 0 ;
2012-11-23 01:02:22 +00:00
for ( int iParticle = 0 ; iParticle < KRENGINE_MAX_RANDOM_PARTICLES ; iParticle + + ) {
2016-08-07 18:39:47 -07:00
vertex_data [ iVertex ] . vertex . x = ( float ) ( rand ( ) % 2000 ) / 1000.0f - 1000.0f ;
vertex_data [ iVertex ] . vertex . y = ( float ) ( rand ( ) % 2000 ) / 1000.0f - 1000.0f ;
vertex_data [ iVertex ] . vertex . z = ( float ) ( rand ( ) % 2000 ) / 1000.0f - 1000.0f ;
2022-02-28 20:36:54 -08:00
vertex_data [ iVertex ] . uva . x = - 0.5f ;
vertex_data [ iVertex ] . uva . y = - inscribed_circle_radius ;
2012-11-02 20:50:45 +00:00
iVertex + + ;
2013-11-09 16:08:08 -08:00
vertex_data [ iVertex ] . vertex . x = vertex_data [ iVertex - 1 ] . vertex . x ;
vertex_data [ iVertex ] . vertex . y = vertex_data [ iVertex - 1 ] . vertex . y ;
vertex_data [ iVertex ] . vertex . z = vertex_data [ iVertex - 1 ] . vertex . z ;
2022-02-28 20:36:54 -08:00
vertex_data [ iVertex ] . uva . x = 0.5f ;
vertex_data [ iVertex ] . uva . y = - inscribed_circle_radius ;
2012-11-02 20:50:45 +00:00
iVertex + + ;
2013-11-09 16:08:08 -08:00
vertex_data [ iVertex ] . vertex . x = vertex_data [ iVertex - 1 ] . vertex . x ;
vertex_data [ iVertex ] . vertex . y = vertex_data [ iVertex - 1 ] . vertex . y ;
vertex_data [ iVertex ] . vertex . z = vertex_data [ iVertex - 1 ] . vertex . z ;
2022-02-28 20:36:54 -08:00
vertex_data [ iVertex ] . uva . x = 0.0f ;
vertex_data [ iVertex ] . uva . y = - inscribed_circle_radius + equilateral_triangle_height ;
2012-11-02 20:50:45 +00:00
iVertex + + ;
}
2013-11-09 16:08:08 -08:00
m_randomParticleVertexData . unlock ( ) ;
2012-11-02 20:50:45 +00:00
}
return m_randomParticleVertexData ;
}
2013-03-21 17:32:26 -07:00
long KRMeshManager : : getMemoryTransferedThisFrame ( )
{
return m_memoryTransferredThisFrame ;
}
2019-01-14 21:07:32 -08:00
size_t KRMeshManager : : getActiveVBOCount ( )
2013-03-21 17:32:26 -07:00
{
return m_vbosActive . size ( ) ;
}
2013-03-21 19:58:35 -07:00
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 ) {
draw_call_info info ;
info . pass = pass ;
strncpy ( info . object_name , object_name . c_str ( ) , 256 ) ;
strncpy ( info . material_name , material_name . c_str ( ) , 256 ) ;
info . vertex_count = vertex_count ;
m_draw_calls . push_back ( info ) ;
}
}
std : : vector < KRMeshManager : : draw_call_info > KRMeshManager : : getDrawCalls ( )
{
m_draw_call_log_used = true ;
return m_draw_calls ;
}
2014-05-13 21:56:06 -07:00
2014-05-13 23:49:03 -07:00
KRMeshManager : : KRVBOData : : KRVBOData ( )
{
2022-02-07 23:38:57 -08:00
m_debugLabel [ 0 ] = ' \0 ' ;
2014-05-27 22:51:52 -07:00
m_is_vbo_loaded = false ;
m_is_vbo_ready = false ;
2014-05-25 23:11:15 -07:00
m_manager = NULL ;
2014-05-27 22:51:52 -07:00
m_type = STREAMING ;
2014-05-15 23:33:01 -07:00
m_data = NULL ;
m_index_data = NULL ;
m_vertex_attrib_flags = 0 ;
m_size = 0 ;
2014-05-25 23:11:15 -07:00
m_last_frame_used = 0 ;
m_last_frame_max_lod_coverage = 0.0f ;
2022-01-22 01:01:08 -08:00
memset ( m_allocations , 0 , sizeof ( AllocationInfo ) * KRENGINE_MAX_GPU_COUNT ) ;
2014-05-13 23:49:03 -07:00
}
2022-02-07 23:38:57 -08:00
KRMeshManager : : KRVBOData : : KRVBOData ( KRMeshManager * manager , KRDataBlock & data , KRDataBlock & index_data , int vertex_attrib_flags , bool static_vbo , vbo_type t
# if KRENGINE_DEBUG_GPU_LABELS
, const char * debug_label
# endif
)
2014-05-13 23:49:03 -07:00
{
2022-02-07 23:38:57 -08:00
m_debugLabel [ 0 ] = ' \0 ' ;
2022-01-22 01:01:08 -08:00
memset ( m_allocations , 0 , sizeof ( AllocationInfo ) * KRENGINE_MAX_GPU_COUNT ) ;
2014-05-28 00:02:36 -07:00
m_is_vbo_loaded = false ;
m_is_vbo_ready = false ;
2022-02-07 23:38:57 -08:00
init ( manager , data , index_data , vertex_attrib_flags , static_vbo , t
# if KRENGINE_DEBUG_GPU_LABELS
, debug_label
# endif
) ;
2014-05-13 23:49:03 -07:00
}
2022-02-07 23:38:57 -08:00
void KRMeshManager : : KRVBOData : : init ( KRMeshManager * manager , KRDataBlock & data , KRDataBlock & index_data , int vertex_attrib_flags , bool static_vbo , vbo_type t
# if KRENGINE_DEBUG_GPU_LABELS
, const char * debug_label
# endif
)
2014-05-13 23:49:03 -07:00
{
2022-02-07 23:38:57 -08:00
# if KRENGINE_DEBUG_GPU_LABELS
snprintf ( m_debugLabel , KRENGINE_DEBUG_GPU_LABEL_MAX_LEN , debug_label ) ;
# endif //KRENGINE_DEBUG_GPU_LABELS
2014-05-25 23:11:15 -07:00
m_manager = manager ;
2014-05-27 22:51:52 -07:00
m_type = t ;
2014-05-15 23:33:01 -07:00
m_static_vbo = static_vbo ;
m_data = & data ;
m_index_data = & index_data ;
m_vertex_attrib_flags = vertex_attrib_flags ;
m_size = m_data - > getSize ( ) ;
if ( m_index_data ! = NULL ) {
m_size + = m_index_data - > getSize ( ) ;
2014-05-13 23:49:03 -07:00
}
2022-01-21 23:32:00 -08:00
if ( t = = KRVBOData : : CONSTANT ) {
m_manager - > primeVBO ( this ) ;
}
2014-05-13 23:49:03 -07:00
}
2014-05-15 23:33:01 -07:00
KRMeshManager : : KRVBOData : : ~ KRVBOData ( )
2014-05-13 23:49:03 -07:00
{
2022-01-22 01:32:32 -08:00
// TODO - This needs to be done by the streamer thread, and asserted here...
2014-05-27 22:51:52 -07:00
unload ( ) ;
2014-05-13 23:49:03 -07:00
}
2014-05-15 23:33:01 -07:00
void KRMeshManager : : KRVBOData : : load ( )
2014-05-13 23:49:03 -07:00
{
2022-01-22 01:32:32 -08:00
// TODO - We should load on each GPU only if there is a surface using the mesh
2014-05-27 22:51:52 -07:00
if ( isVBOLoaded ( ) ) {
2014-05-20 23:05:43 -07:00
return ;
}
2022-01-21 23:38:36 -08:00
2022-01-22 01:01:08 -08:00
KRDeviceManager * deviceManager = m_manager - > getContext ( ) . getDeviceManager ( ) ;
int iAllocation = 0 ;
for ( auto deviceItr = deviceManager - > getDevices ( ) . begin ( ) ; deviceItr ! = deviceManager - > getDevices ( ) . end ( ) & & iAllocation < KRENGINE_MAX_GPU_COUNT ; deviceItr + + , iAllocation + + ) {
KRDevice & device = * ( * deviceItr ) . second ;
KrDeviceHandle deviceHandle = ( * deviceItr ) . first ;
2022-07-09 23:52:35 -07:00
VmaAllocator allocator = device . getAllocator ( ) ;
2022-01-22 01:01:08 -08:00
AllocationInfo & allocation = m_allocations [ iAllocation ] ;
allocation . device = deviceHandle ;
2022-02-07 23:38:57 -08:00
# if KRENGINE_DEBUG_GPU_LABELS
char debug_label [ KRENGINE_DEBUG_GPU_LABEL_MAX_LEN ] ;
char * type_label = " " ;
switch ( m_type ) {
case vbo_type : : STREAMING :
type_label = " Streaming " ;
break ;
case vbo_type : : CONSTANT :
type_label = " Constant " ;
break ;
case vbo_type : : TEMPORARY :
type_label = " Temporary " ;
break ;
default :
assert ( false ) ;
}
snprintf ( debug_label , KRENGINE_DEBUG_GPU_LABEL_MAX_LEN , " %s Vertices: %s " , type_label , m_debugLabel ) ;
2022-07-10 00:15:18 -07:00
# endif // KRENGINE_DEBUG_GPU_LABELS
2022-02-07 23:38:57 -08:00
2022-07-10 00:15:18 -07:00
device . createBuffer (
m_data - > getSize ( ) ,
VK_BUFFER_USAGE_VERTEX_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT ,
2022-07-12 00:48:53 -07:00
VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT ,
2022-07-10 00:15:18 -07:00
& allocation . vertex_buffer ,
& allocation . vertex_allocation
# if KRENGINE_DEBUG_GPU_LABELS
, debug_label
2022-02-07 23:38:57 -08:00
# endif // KRENGINE_DEBUG_GPU_LABELS
2022-07-10 00:15:18 -07:00
) ;
2022-07-12 00:48:53 -07:00
device . streamUpload ( * m_data , allocation . vertex_buffer ) ;
2022-01-22 01:01:08 -08:00
if ( m_index_data - > getSize ( ) > 0 ) {
2022-07-10 00:15:18 -07:00
# if KRENGINE_DEBUG_GPU_LABELS
snprintf ( debug_label , KRENGINE_DEBUG_GPU_LABEL_MAX_LEN , " %s Indexes: %s " , type_label , m_debugLabel ) ;
# endif // KRENGINE_DEBUG_GPU_LABELS
2022-07-09 23:52:35 -07:00
device . createBuffer (
m_index_data - > getSize ( ) ,
VK_BUFFER_USAGE_INDEX_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT ,
2022-07-12 00:48:53 -07:00
VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT ,
2022-07-09 23:52:35 -07:00
& allocation . index_buffer ,
& allocation . index_allocation
2022-02-07 23:38:57 -08:00
# if KRENGINE_DEBUG_GPU_LABELS
2022-07-10 00:15:18 -07:00
, debug_label
# endif
) ;
2022-07-12 00:48:53 -07:00
device . streamUpload ( * m_index_data , allocation . index_buffer ) ;
2022-01-22 01:01:08 -08:00
}
}
2014-05-27 22:51:52 -07:00
m_is_vbo_loaded = true ;
2014-06-03 02:40:56 -07:00
m_manager - > m_vboMemUsed + = getSize ( ) ;
m_manager - > m_memoryTransferredThisFrame + = getSize ( ) ;
2014-05-27 22:51:52 -07:00
if ( m_type = = CONSTANT ) {
2014-05-28 00:02:36 -07:00
_swapHandles ( ) ;
2014-05-27 22:51:52 -07:00
}
2014-05-13 23:49:03 -07:00
}
2014-05-15 23:33:01 -07:00
void KRMeshManager : : KRVBOData : : unload ( )
{
2022-01-22 01:32:32 -08:00
KRDeviceManager * deviceManager = m_manager - > getContext ( ) . getDeviceManager ( ) ;
for ( int i = 0 ; i < KRENGINE_MAX_GPU_COUNT ; i + + ) {
AllocationInfo & allocation = m_allocations [ i ] ;
if ( allocation . device ) {
std : : unique_ptr < KRDevice > & device = deviceManager - > getDevice ( allocation . device ) ;
if ( device ) {
VmaAllocator allocator = device - > getAllocator ( ) ;
vmaDestroyBuffer ( allocator , allocation . vertex_buffer , allocation . vertex_allocation ) ;
if ( allocation . index_buffer ) {
vmaDestroyBuffer ( allocator , allocation . index_buffer , allocation . index_allocation ) ;
}
}
2014-05-15 23:33:01 -07:00
}
2022-01-22 01:32:32 -08:00
memset ( & allocation , 0 , sizeof ( AllocationInfo ) ) ;
}
if ( isVBOLoaded ( ) ) {
m_manager - > m_vboMemUsed - = getSize ( ) ;
}
2014-05-27 22:51:52 -07:00
2022-01-22 01:32:32 -08:00
m_is_vbo_loaded = false ;
m_is_vbo_ready = false ;
2014-05-15 23:33:01 -07:00
}
2022-02-28 01:07:32 -08:00
void KRMeshManager : : KRVBOData : : bind ( VkCommandBuffer & commandBuffer )
{
VkBuffer vertexBuffers [ ] = { getVertexBuffer ( ) } ;
VkDeviceSize offsets [ ] = { 0 } ;
vkCmdBindVertexBuffers ( commandBuffer , 0 , 1 , vertexBuffers , offsets ) ;
2022-07-06 23:51:43 -07:00
if ( m_index_data - > getSize ( ) > 0 ) {
// TODO - Support 32-bit index buffers
vkCmdBindIndexBuffer ( commandBuffer , getIndexBuffer ( ) , 0 , VK_INDEX_TYPE_UINT16 ) ;
}
2022-02-28 01:07:32 -08:00
}
2014-05-25 23:11:15 -07:00
void KRMeshManager : : KRVBOData : : resetPoolExpiry ( float lodCoverage )
{
long current_frame = m_manager - > getContext ( ) . getCurrentFrame ( ) ;
if ( current_frame ! = m_last_frame_used ) {
m_last_frame_used = current_frame ;
m_last_frame_max_lod_coverage = 0.0f ;
2014-05-27 22:51:52 -07:00
m_manager - > primeVBO ( this ) ;
2014-05-25 23:11:15 -07:00
}
m_last_frame_max_lod_coverage = KRMAX ( lodCoverage , m_last_frame_max_lod_coverage ) ;
2014-05-27 22:51:52 -07:00
}
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 ;
}
}
2022-02-13 22:22:51 -08:00
VkBuffer & KRMeshManager : : KRVBOData : : getVertexBuffer ( )
{
assert ( m_is_vbo_ready ) ;
return m_allocations - > vertex_buffer ;
}
VkBuffer & KRMeshManager : : KRVBOData : : getIndexBuffer ( )
{
assert ( m_is_vbo_ready ) ;
return m_allocations - > index_buffer ;
}
2022-02-27 23:51:29 -08:00
uint32_t KRMeshManager : : KRVBOData : : getVertexAttributes ( )
{
return m_vertex_attrib_flags ;
}