413 lines
12 KiB
C++
413 lines
12 KiB
C++
//
|
|
// Created by kj16609 on 11/27/23.
|
|
//
|
|
|
|
#include "EngineContext.hpp"
|
|
|
|
#include <glm/glm.hpp>
|
|
#include <tracy/TracyC.h>
|
|
#include <tracy/TracyVulkan.hpp>
|
|
|
|
#include <chrono>
|
|
#include <iostream>
|
|
|
|
#include "KeyboardMovementController.hpp"
|
|
#include "assets/stores.hpp"
|
|
#include "engine/Average.hpp"
|
|
#include "engine/buffers/UniqueFrameSuballocation.hpp"
|
|
#include "engine/debug/drawers.hpp"
|
|
#include "engine/literals/size.hpp"
|
|
#include "engine/model/prebuilt/terrainModel.hpp"
|
|
#include "engine/pipeline/PipelineT.hpp"
|
|
#include "engine/systems/EntityRendererSystem.hpp"
|
|
#include "gui/core.hpp"
|
|
#include "model/builders/SceneBuilder.hpp"
|
|
|
|
namespace fgl::engine
|
|
{
|
|
constexpr float MAX_DELTA_TIME { 0.5 };
|
|
|
|
EngineContext::EngineContext()
|
|
{
|
|
ZoneScoped;
|
|
using namespace fgl::literals::size_literals;
|
|
initGlobalStagingBuffer( 512_MiB );
|
|
#if ENABLE_IMGUI
|
|
initImGui();
|
|
#endif
|
|
loadGameObjects();
|
|
}
|
|
|
|
static Average< float, 60 * 15 > rolling_ms_average;
|
|
|
|
void preStage( vk::raii::CommandBuffer& cmd_buffer )
|
|
{
|
|
ZoneScopedN( "Pre-Stage" );
|
|
|
|
getTextureStore().stage( cmd_buffer );
|
|
}
|
|
|
|
void postStage()
|
|
{
|
|
ZoneScopedN( "Post-Stage" );
|
|
getTextureStore().confirmStaged();
|
|
}
|
|
|
|
void EngineContext::run()
|
|
{
|
|
TracyCZoneN( TRACY_PrepareEngine, "Inital Run", true );
|
|
std::cout << "Starting main loop run" << std::endl;
|
|
using namespace fgl::literals::size_literals;
|
|
Buffer global_ubo_buffer { 512_KiB,
|
|
vk::BufferUsageFlagBits::eUniformBuffer,
|
|
vk::MemoryPropertyFlagBits::eHostVisible }; // 512 KB
|
|
|
|
PerFrameSuballocation< HostSingleT< CameraInfo > > camera_info { global_ubo_buffer,
|
|
SwapChain::MAX_FRAMES_IN_FLIGHT };
|
|
|
|
PerFrameSuballocation< HostSingleT< PointLight > > point_lights { global_ubo_buffer,
|
|
SwapChain::MAX_FRAMES_IN_FLIGHT };
|
|
|
|
std::shared_ptr< Texture > debug_tex {
|
|
getTextureStore().load( "assets/textures/DebugTexture.png", vk::Format::eR8G8B8A8Unorm )
|
|
};
|
|
|
|
constexpr std::uint32_t matrix_default_size { 64_MiB };
|
|
constexpr std::uint32_t draw_parameter_default_size { 64_MiB };
|
|
|
|
std::vector< Buffer > matrix_info_buffers {};
|
|
|
|
std::vector< Buffer > draw_parameter_buffers {};
|
|
|
|
std::vector< DescriptorSet > global_descriptor_sets {};
|
|
|
|
for ( int i = 0; i < SwapChain::MAX_FRAMES_IN_FLIGHT; ++i )
|
|
{
|
|
matrix_info_buffers.emplace_back(
|
|
matrix_default_size,
|
|
vk::BufferUsageFlagBits::eVertexBuffer,
|
|
vk::MemoryPropertyFlagBits::eDeviceLocal | vk::MemoryPropertyFlagBits::eHostVisible );
|
|
|
|
draw_parameter_buffers.emplace_back(
|
|
draw_parameter_default_size,
|
|
vk::BufferUsageFlagBits::eIndirectBuffer,
|
|
vk::MemoryPropertyFlagBits::eDeviceLocal | vk::MemoryPropertyFlagBits::eHostVisible );
|
|
|
|
global_descriptor_sets.emplace_back( GlobalDescriptorSet::createLayout() );
|
|
}
|
|
|
|
for ( std::uint8_t i = 0; i < SwapChain::MAX_FRAMES_IN_FLIGHT; ++i )
|
|
{
|
|
global_descriptor_sets[ i ].setMaxIDX( 2 );
|
|
global_descriptor_sets[ i ].bindUniformBuffer( 0, camera_info[ i ] );
|
|
global_descriptor_sets[ i ].bindUniformBuffer( 2, point_lights[ i ] );
|
|
global_descriptor_sets[ i ].update();
|
|
}
|
|
|
|
Camera camera {};
|
|
debug::setDebugDrawingCamera( camera );
|
|
|
|
auto viewer { GameObject::createGameObject() };
|
|
|
|
viewer.m_transform.translation = WorldCoordinate( constants::WORLD_CENTER + glm::vec3( 0.0f, 0.0f, 2.5f ) );
|
|
|
|
KeyboardMovementController camera_controller {};
|
|
|
|
auto current_time { std::chrono::high_resolution_clock::now() };
|
|
|
|
auto previous_frame_start { std::chrono::high_resolution_clock::now() };
|
|
|
|
//camera.setOrthographicProjection( -aspect, aspect, -1, 1, -1, 1 );
|
|
const float aspect { m_renderer.getAspectRatio() };
|
|
camera.setPerspectiveProjection( glm::radians( 90.0f ), aspect, constants::NEAR_PLANE, constants::FAR_PLANE );
|
|
|
|
const auto old_aspect_ratio { m_renderer.getAspectRatio() };
|
|
|
|
TracyCZoneEnd( TRACY_PrepareEngine );
|
|
|
|
while ( !m_window.shouldClose() )
|
|
{
|
|
ZoneScopedN( "Poll" );
|
|
glfwPollEvents();
|
|
|
|
const auto new_time { std::chrono::high_resolution_clock::now() };
|
|
|
|
{
|
|
//Calculate time change from previous frame and add to accumulator
|
|
const auto time_diff { new_time - previous_frame_start };
|
|
rolling_ms_average.push(
|
|
static_cast< float >( std::chrono::duration_cast< std::chrono::microseconds >( time_diff ).count() )
|
|
/ 1000.0f );
|
|
previous_frame_start = new_time;
|
|
}
|
|
|
|
auto delta_time { std::chrono::duration< float >( new_time - current_time ).count() };
|
|
|
|
current_time = new_time;
|
|
delta_time = glm::min( delta_time, MAX_DELTA_TIME );
|
|
|
|
if ( old_aspect_ratio != m_renderer.getAspectRatio() )
|
|
{
|
|
camera.setPerspectiveProjection(
|
|
glm::radians( 90.0f ), m_renderer.getAspectRatio(), constants::NEAR_PLANE, constants::FAR_PLANE );
|
|
}
|
|
|
|
camera_controller.moveInPlaneXZ( m_window.window(), delta_time, viewer );
|
|
camera.setView( viewer.getPosition(), viewer.getRotation() );
|
|
|
|
if ( auto [ command_buffer, gui_command_buffer ] = m_renderer.beginFrame(); *command_buffer )
|
|
{
|
|
preStage( command_buffer );
|
|
|
|
ZoneScopedN( "Render" );
|
|
//Update
|
|
const std::uint16_t frame_index { m_renderer.getFrameIndex() };
|
|
|
|
const auto view_frustum { camera.getFrustumBounds() };
|
|
|
|
FrameInfo frame_info { frame_index,
|
|
delta_time,
|
|
command_buffer,
|
|
gui_command_buffer,
|
|
{ camera, viewer.m_transform },
|
|
global_descriptor_sets[ frame_index ],
|
|
m_game_objects_root,
|
|
m_renderer.getCurrentTracyCTX(),
|
|
matrix_info_buffers[ frame_index ],
|
|
draw_parameter_buffers[ frame_index ],
|
|
m_renderer.getGBufferDescriptor( frame_index ),
|
|
m_renderer.getGBufferCompositeDescriptor( frame_index ),
|
|
view_frustum,
|
|
this->m_renderer.getSwapChain() };
|
|
|
|
#if TRACY_ENABLE
|
|
//auto& tracy_ctx { frame_info.tracy_ctx };
|
|
#endif
|
|
|
|
CameraInfo current_camera_info { .projection = camera.getProjectionMatrix(),
|
|
.view = camera.getViewMatrix(),
|
|
.inverse_view = camera.getInverseViewMatrix() };
|
|
|
|
camera_info[ frame_index ] = current_camera_info;
|
|
|
|
m_culling_system.startPass( frame_info );
|
|
TracyVkCollect( frame_info.tracy_ctx, *command_buffer );
|
|
m_culling_system.wait();
|
|
|
|
m_renderer.beginSwapchainRendererPass( command_buffer );
|
|
|
|
m_terrain_system.pass( frame_info );
|
|
|
|
m_entity_renderer.pass( frame_info );
|
|
|
|
m_composition_system.pass( frame_info );
|
|
|
|
m_gui_system.pass( frame_info );
|
|
|
|
m_renderer.endSwapchainRendererPass( command_buffer );
|
|
|
|
m_renderer.endFrame();
|
|
|
|
FrameMark;
|
|
}
|
|
|
|
postStage();
|
|
}
|
|
|
|
Device::getInstance().device().waitIdle();
|
|
}
|
|
|
|
void EngineContext::loadGameObjects()
|
|
{
|
|
ZoneScoped;
|
|
std::cout << "Loading game objects" << std::endl;
|
|
auto command_buffer { Device::getInstance().beginSingleTimeCommands() };
|
|
|
|
/*
|
|
{
|
|
std::shared_ptr< Model > model { Model::createModel(
|
|
Device::getInstance(),
|
|
"assets/night_heron8.obj",
|
|
m_entity_renderer.getVertexBuffer(),
|
|
m_entity_renderer.getIndexBuffer() ) };
|
|
|
|
for ( int i = 0; i < 16; ++i )
|
|
{
|
|
auto night_heron = GameObject::createGameObject();
|
|
night_heron.model = model;
|
|
night_heron.transform.translation = { -5.0f + ( i * 1.0 ), 0.5f, 0.0f };
|
|
night_heron.transform.scale = { 0.05f, 0.05f, 0.05f };
|
|
night_heron.transform.rotation = { 0.0f, 0.0f, 0.0f };
|
|
|
|
night_heron.model->syncBuffers( command_buffer );
|
|
|
|
game_objects.emplace( night_heron.getId(), std::move( night_heron ) );
|
|
}
|
|
}*/
|
|
|
|
/*
|
|
{
|
|
std::shared_ptr< Model > model { Model::createModel(
|
|
Device::getInstance(),
|
|
"assets/khronos-sponza/Sponza.gltf",
|
|
m_entity_renderer.getVertexBuffer(),
|
|
m_entity_renderer.getIndexBuffer() ) };
|
|
|
|
assert( model );
|
|
|
|
model->stage( command_buffer );
|
|
|
|
constexpr int x_val { 1 };
|
|
constexpr int y_val { x_val };
|
|
|
|
for ( int x = 0; x < x_val; ++x )
|
|
{
|
|
for ( int y = 0; y < y_val; ++y )
|
|
{
|
|
auto sponza = GameObject::createGameObject();
|
|
sponza.object_flags |= IS_ENTITY | IS_VISIBLE;
|
|
sponza.m_model = model;
|
|
sponza.m_transform.translation = WorldCoordinate( constants::WORLD_CENTER );
|
|
// 0.0f );
|
|
sponza.m_transform.scale = { 0.007f, 0.007f, 0.007f };
|
|
sponza.m_transform.rotation = Rotation( 0.0f, 0.0f, 0.0f );
|
|
|
|
m_game_objects_root.addGameObject( std::move( sponza ) );
|
|
}
|
|
}
|
|
}
|
|
*/
|
|
|
|
{
|
|
ZoneScopedN( "Load phyiscs test" );
|
|
std::vector< std::shared_ptr< Model > > assets { Model::createModelsFromScene(
|
|
Device::getInstance(),
|
|
"assets/PhysicsTest.glb",
|
|
m_entity_renderer.getVertexBuffer(),
|
|
m_entity_renderer.getIndexBuffer() ) };
|
|
|
|
for ( auto& model : assets )
|
|
{
|
|
GameObject object { GameObject::createGameObject() };
|
|
object.m_model = std::move( model );
|
|
object.m_transform.translation = WorldCoordinate( 0.0f );
|
|
object.object_flags |= IS_VISIBLE | IS_ENTITY;
|
|
|
|
assert( object.m_model );
|
|
object.m_model->stage( command_buffer );
|
|
|
|
m_game_objects_root.addGameObject( std::move( object ) );
|
|
}
|
|
}
|
|
|
|
/*
|
|
{
|
|
ZoneScopedN( "Load terrain" );
|
|
auto model {
|
|
generateTerrainModel( m_terrain_system.getVertexBuffer(), m_terrain_system.getIndexBuffer() )
|
|
};
|
|
|
|
//Texture texture { Texture::loadFromFile( "assets/Vally/textures/heightmap.png" ) };
|
|
Texture texture { Texture::generateFromPerlinNoise( 1024, 1024, 120 ) };
|
|
|
|
Sampler sampler { vk::Filter::eLinear,
|
|
vk::Filter::eLinear,
|
|
vk::SamplerMipmapMode::eLinear,
|
|
vk::SamplerAddressMode::eClampToEdge };
|
|
texture.getImageView().getSampler() = std::move( sampler );
|
|
texture.createImGuiSet();
|
|
Texture::getTextureDescriptorSet().bindTexture( 0, texture );
|
|
Texture::getTextureDescriptorSet().update();
|
|
|
|
model->m_primitives[ 0 ].m_texture = std::move( texture );
|
|
|
|
model->syncBuffers( command_buffer );
|
|
|
|
auto floor { GameObject::createGameObject() };
|
|
floor.object_flags |= IS_TERRAIN | IS_VISIBLE;
|
|
floor.m_model = model;
|
|
assert( floor.m_model->m_primitives.size() == 1 );
|
|
|
|
floor.m_transform.translation = WorldCoordinate( constants::WORLD_CENTER );
|
|
|
|
m_game_objects_root.addGameObject( std::move( floor ) );
|
|
}
|
|
*/
|
|
|
|
/*
|
|
{
|
|
std::shared_ptr< Model > model { Model::createModel(
|
|
Device::getInstance(),
|
|
"assets/smooth_vase.obj",
|
|
m_entity_renderer.getVertexBuffer(),
|
|
m_entity_renderer.getIndexBuffer() ) };
|
|
|
|
auto smooth_vase = GameObject::createGameObject();
|
|
smooth_vase.model = model;
|
|
|
|
smooth_vase.transform.translation = { -0.5f, 0.5f, .0f };
|
|
smooth_vase.transform.scale = { 3.0f, 1.5f, 3.0f };
|
|
|
|
smooth_vase.model->syncBuffers( command_buffer );
|
|
|
|
game_objects.emplace( smooth_vase.getId(), std::move( smooth_vase ) );
|
|
}
|
|
|
|
{
|
|
std::shared_ptr< Model > flat_model { Model::createModel(
|
|
Device::getInstance(),
|
|
"assets/flat_vase.obj",
|
|
m_entity_renderer.getVertexBuffer(),
|
|
m_entity_renderer.getIndexBuffer() ) };
|
|
|
|
auto flat_vase = GameObject::createGameObject();
|
|
flat_vase.model = flat_model;
|
|
//flat_vase.transform.translation = { 0.5f, 0.5f, 0.0f };
|
|
flat_vase.transform.translation = { 0.5f, 0.5f, 0.0f };
|
|
flat_vase.transform.scale = { 3.0f, 1.5f, 3.0f };
|
|
|
|
flat_vase.model->syncBuffers( command_buffer );
|
|
|
|
game_objects.emplace( flat_vase.getId(), std::move( flat_vase ) );
|
|
}
|
|
{
|
|
std::shared_ptr< Model > quad_model { Model::createModel(
|
|
Device::getInstance(),
|
|
"assets/quad.obj",
|
|
m_entity_renderer.getVertexBuffer(),
|
|
m_entity_renderer.getIndexBuffer() ) };
|
|
|
|
auto floor = GameObject::createGameObject();
|
|
floor.model = quad_model;
|
|
floor.transform.translation = { 0.0f, 0.5f, 0.0f };
|
|
floor.transform.scale = { 3.0f, 1.0f, 3.0f };
|
|
floor.is_world = true;
|
|
|
|
floor.model->syncBuffers( command_buffer );
|
|
|
|
game_objects.emplace( floor.getId(), std::move( floor ) );
|
|
}
|
|
*/
|
|
|
|
Device::getInstance().endSingleTimeCommands( command_buffer );
|
|
std::cout << "Finished loading game objects" << std::endl;
|
|
|
|
m_game_objects_root.recalculateBoundingBoxes();
|
|
}
|
|
|
|
void EngineContext::initImGui()
|
|
{
|
|
#if ENABLE_IMGUI
|
|
gui::initGui( m_window, m_renderer );
|
|
#endif
|
|
}
|
|
|
|
EngineContext::~EngineContext()
|
|
{
|
|
#if ENABLE_IMGUI
|
|
gui::cleanupImGui();
|
|
#endif
|
|
}
|
|
|
|
} // namespace fgl::engine
|