#include "HydraShadowBufferManager.h" #include "../scheduler/HydraTaskScheduler.h" #include "../task/buffer/HydraCreateGPUBufferTask.hpp" #include "../task/buffer/HydraUpdateWholeGPUBufferTask.hpp" #include "../task/buffer/HydraUpdatePartialGPUBufferTask.hpp" #include "../task/buffer/HydraCreateUnBoundTextureTask.hpp" #include "../task/buffer/HydraDeleteGPUBufferTask.hpp" #include "../task/renderer/HydraCreateCascadeShadowFrameBuffer.hpp" #include "../task/renderer/HydraCreateCubemapShadowFrameBuffer.hpp" #include "../task/renderer/HydraCreateShadowFrameBuffer.hpp" #include "../task/renderer/HydraDeleteShadowFrameBufferTask.hpp" #include "../ecs/components/HydraDirectionalShadowSourceComponent.h" void HydraShadowBufferManager::Initialise() { HydraTaskScheduler *task_scheduler = GetEngine()->TaskScheduler(); for(uint32_t i = 0; i < MAX_DIRECTIONAL_SHADOWS; i++) { m_available_dir.push(i); } for(uint32_t i = 0; i < MAX_SPOT_SHADOWS; i++) { m_available_spot.push(i); } for(uint32_t i = 0; i < MAX_POINT_SHADOWS; i++) { m_available_point.push(i); } m_directional_shadow_buffer.resize(MAX_DIRECTIONAL_SHADOWS); m_spot_shadow_buffer.resize(MAX_SPOT_SHADOWS); m_point_shadow_buffer.resize(MAX_POINT_SHADOWS); uint32_t buffer_size = (MAX_DIRECTIONAL_SHADOWS * sizeof(HydraDirectionalShadowSourceComponent)); HydraID create_gpu_buffer_task_id = task_scheduler->CreateTask(HydraThreadAffinity::Render); HydraCreateGPUBufferTask *task = static_cast(task_scheduler->GetTask(create_gpu_buffer_task_id)); task->Intialise("DirectionalShadowBuffer", 1, buffer_size, &m_directional_shadow_buffer_id, HYDRA_BUFFER_TYPE::HYDRA_SSBO_BUFFER); task_scheduler->WaitForTask(create_gpu_buffer_task_id); buffer_size = (MAX_SPOT_SHADOWS * sizeof(HydraSpotShadowSourceComponent)); create_gpu_buffer_task_id = task_scheduler->CreateTask(HydraThreadAffinity::Render); HydraCreateGPUBufferTask *spot_task = static_cast(task_scheduler->GetTask(create_gpu_buffer_task_id)); spot_task->Intialise("SpotShadowBuffer", 1, buffer_size, &m_spot_shadow_buffer_id, HYDRA_BUFFER_TYPE::HYDRA_SSBO_BUFFER); task_scheduler->WaitForTask(create_gpu_buffer_task_id); buffer_size = (MAX_POINT_SHADOWS * sizeof(HydraPointShadowSourceComponent)); create_gpu_buffer_task_id = task_scheduler->CreateTask(HydraThreadAffinity::Render); HydraCreateGPUBufferTask *point_task = static_cast(task_scheduler->GetTask(create_gpu_buffer_task_id)); point_task->Intialise("PointShadowBuffer", 1, buffer_size, &m_point_shadow_buffer_id, HYDRA_BUFFER_TYPE::HYDRA_SSBO_BUFFER); task_scheduler->WaitForTask(create_gpu_buffer_task_id); } void HydraShadowBufferManager::Shutdown() { HydraTaskScheduler *task_scheduler = GetEngine()->TaskScheduler(); uint32_t delete_gpu_buffer_task_id = task_scheduler->CreateTask(HydraThreadAffinity::Render); HydraDeleteGPUBufferTask *point_task = static_cast(task_scheduler->GetTask(delete_gpu_buffer_task_id)); point_task->Intialise(m_point_shadow_buffer_id); task_scheduler->WaitForTask(delete_gpu_buffer_task_id); delete_gpu_buffer_task_id = task_scheduler->CreateTask(HydraThreadAffinity::Render); HydraDeleteGPUBufferTask *dir_task = static_cast(task_scheduler->GetTask(delete_gpu_buffer_task_id)); dir_task->Intialise(m_directional_shadow_buffer_id); task_scheduler->WaitForTask(delete_gpu_buffer_task_id); delete_gpu_buffer_task_id = task_scheduler->CreateTask(HydraThreadAffinity::Render); HydraDeleteGPUBufferTask *spot_task = static_cast(task_scheduler->GetTask(delete_gpu_buffer_task_id)); spot_task->Intialise(m_point_shadow_buffer_id); task_scheduler->WaitForTask(delete_gpu_buffer_task_id); } HydraID HydraShadowBufferManager::AddDirectionalShadow(HydraDirectionalShadowSourceComponent& shadow) { std::lock_guard lock(m_mutex); if(m_available_dir.size() == 0) { return INVALID_HYDRA_ID; } HydraID shadow_id = m_available_dir.front(); shadow.shadow_id = shadow_id; m_directional_shadow_buffer[shadow_id] = shadow; HydraEngine *engine = GetEngine(); HydraECS *ecs = engine->ECS(); HydraTaskScheduler *task_scheduler = GetEngine()->TaskScheduler(); uint32_t depth_texture_id = 0; uint32_t frame_buffer_id = 0; HydraID create_framebuffer_task_id = task_scheduler->CreateTask(HydraThreadAffinity::Render); HydraCreateCascadeShadowFrameBuffer *fb_task = static_cast(task_scheduler->GetTask(create_framebuffer_task_id)); fb_task->Initialise(&depth_texture_id, &frame_buffer_id); task_scheduler->WaitForTask(create_framebuffer_task_id); shadow.shadow_texture_id = depth_texture_id; shadow.frame_buffer_id = frame_buffer_id; return shadow_id; } HydraID HydraShadowBufferManager::AddSpotShadow(HydraSpotShadowSourceComponent& shadow) { std::lock_guard lock(m_mutex); if(m_available_spot.size() == 0) { return INVALID_HYDRA_ID; } HydraID shadow_id = m_available_spot.front(); m_spot_shadow_buffer[shadow_id] = shadow; HydraEngine *engine = GetEngine(); HydraECS *ecs = engine->ECS(); HydraTaskScheduler *task_scheduler = GetEngine()->TaskScheduler(); uint32_t depth_texture_id = 0; uint32_t frame_buffer_id = 0; HydraID create_framebuffer_task_id = task_scheduler->CreateTask(HydraThreadAffinity::Render); HydraCreateShadowFrameBuffer *fb_task = static_cast(task_scheduler->GetTask(create_framebuffer_task_id)); fb_task->Initialise(&depth_texture_id, &frame_buffer_id); task_scheduler->WaitForTask(create_framebuffer_task_id); shadow.shadow_texture_id = depth_texture_id; shadow.frame_buffer_id = frame_buffer_id; return shadow_id; } HydraID HydraShadowBufferManager::AddPointShadow(HydraPointShadowSourceComponent& shadow) { std::lock_guard lock(m_mutex); if(m_available_point.size() == 0) { return INVALID_HYDRA_ID; } HydraID shadow_id = m_available_point.front(); m_point_shadow_buffer[shadow_id] = shadow; HydraEngine *engine = GetEngine(); HydraECS *ecs = engine->ECS(); HydraTaskScheduler *task_scheduler = GetEngine()->TaskScheduler(); uint32_t depth_texture_id = 0; uint32_t frame_buffer_id = 0; HydraID create_framebuffer_task_id = task_scheduler->CreateTask(HydraThreadAffinity::Render); HydraCreateCubemapShadowFrameBuffer *fb_task = static_cast(task_scheduler->GetTask(create_framebuffer_task_id)); fb_task->Initialise( &depth_texture_id, &frame_buffer_id); task_scheduler->WaitForTask(create_framebuffer_task_id); shadow.shadow_texture_id = depth_texture_id; shadow.frame_buffer_id = frame_buffer_id; return shadow_id; } void HydraShadowBufferManager::UpdateDirectionalShadow(HydraID shadow_id, HydraDirectionalShadowSourceComponent shadow) { std::lock_guard lock(m_mutex); if(shadow_id < MAX_DIRECTIONAL_SHADOWS) { m_directional_shadow_buffer[shadow_id] = shadow; } } void HydraShadowBufferManager::UpdateSpotShadow(HydraID shadow_id, HydraSpotShadowSourceComponent shadow) { std::lock_guard lock(m_mutex); if(shadow_id < MAX_SPOT_SHADOWS) { m_spot_shadow_buffer[shadow_id] = shadow; } } void HydraShadowBufferManager::UpdatePointShadow(HydraID shadow_id, HydraPointShadowSourceComponent shadow) { std::lock_guard lock(m_mutex); if(shadow_id < MAX_SPOT_SHADOWS) { m_point_shadow_buffer[shadow_id] = shadow; } } void HydraShadowBufferManager::DeleteDirectionalShadow(HydraID shadow_id) { HydraECS* ecs = GetEngine()->ECS(); HydraTaskScheduler* task_scheduler = GetEngine()->TaskScheduler(); HydraDirectionalShadowSourceComponent shadow_comp = m_directional_shadow_buffer[shadow_id]; HydraID delete_frame_buffer_task_id = task_scheduler->CreateTask(HydraThreadAffinity::Render); HydraDeleteShadowFrameBufferTask *fb_task = static_cast(task_scheduler->GetTask(delete_frame_buffer_task_id)); fb_task->Initialise(shadow_comp.shadow_texture_id, shadow_comp.frame_buffer_id); task_scheduler->WaitForTask(delete_frame_buffer_task_id); m_available_dir.push(shadow_id); } void HydraShadowBufferManager::DeleteSpotShadow(HydraID shadow_id) { HydraECS* ecs = GetEngine()->ECS(); HydraTaskScheduler* task_scheduler = GetEngine()->TaskScheduler(); HydraSpotShadowSourceComponent shadow_comp = m_spot_shadow_buffer[shadow_id]; HydraID delete_frame_buffer_task_id = task_scheduler->CreateTask(HydraThreadAffinity::Render); HydraDeleteShadowFrameBufferTask *fb_task = static_cast(task_scheduler->GetTask(delete_frame_buffer_task_id)); fb_task->Initialise(shadow_comp.shadow_texture_id, shadow_comp.frame_buffer_id); task_scheduler->WaitForTask(delete_frame_buffer_task_id); m_available_spot.push(shadow_id); } void HydraShadowBufferManager::DeletePointShadow(HydraID shadow_id) { HydraECS* ecs = GetEngine()->ECS(); HydraTaskScheduler* task_scheduler = GetEngine()->TaskScheduler(); HydraPointShadowSourceComponent shadow_comp = m_point_shadow_buffer[shadow_id]; HydraID delete_frame_buffer_task_id = task_scheduler->CreateTask(HydraThreadAffinity::Render); HydraDeleteShadowFrameBufferTask *fb_task = static_cast(task_scheduler->GetTask(delete_frame_buffer_task_id)); fb_task->Initialise(shadow_comp.shadow_texture_id, shadow_comp.frame_buffer_id); task_scheduler->WaitForTask(delete_frame_buffer_task_id); m_available_point.push(shadow_id); } void HydraShadowBufferManager::UpdateShadowBuffer() { HydraEngine *engine = GetEngine(); HydraECS *ecs = engine->ECS(); HydraTaskScheduler *task_scheduler = GetEngine()->TaskScheduler(); void *buffer = static_cast(m_directional_shadow_buffer.data()); HydraID update_buffer_task_id = task_scheduler->CreateTask(HydraThreadAffinity::Render); HydraUpdateWholeGPUBufferTask *task = static_cast(task_scheduler->GetTask(update_buffer_task_id)); task->Intialise(m_directional_shadow_buffer_id, buffer); task_scheduler->WaitForTask(update_buffer_task_id); void *spot_buffer = static_cast(m_spot_shadow_buffer.data()); update_buffer_task_id = task_scheduler->CreateTask(HydraThreadAffinity::Render); HydraUpdateWholeGPUBufferTask *spot_task = static_cast(task_scheduler->GetTask(update_buffer_task_id)); spot_task->Intialise(m_spot_shadow_buffer_id, spot_buffer); task_scheduler->WaitForTask(update_buffer_task_id); void *point_buffer = static_cast(m_point_shadow_buffer.data()); update_buffer_task_id = task_scheduler->CreateTask(HydraThreadAffinity::Render); HydraUpdateWholeGPUBufferTask *point_task = static_cast(task_scheduler->GetTask(update_buffer_task_id)); point_task->Intialise(m_point_shadow_buffer_id, point_buffer); task_scheduler->WaitForTask(update_buffer_task_id); }