#include "HydraLightBufferManager.h" #include "../scheduler/HydraTaskScheduler.h" #include "../engine/HydraEngine.h" #include "../task/buffer/HydraCreateGPUBufferTask.hpp" #include "../task/buffer/HydraDeleteGPUBufferTask.hpp" #include "../task/buffer/HydraUpdatePartialGPUBufferTask.hpp" #include "../ecs/components/HydraLightComponent.h" void HydraLightBufferManager::Initialise() { m_light_lookup.resize(MAX_LIGHTS); for(uint32_t i = 0; i < MAX_LIGHTS; i ++) { m_available_lights.push(i); m_light_lookup[i] = INVALID_HYDRA_ID; } HydraTaskScheduler *task_scheduler = GetEngine()->TaskScheduler(); 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("LightBuffer", 1, MAX_LIGHTS * sizeof(HydraLightComponent), &m_light_buffer_id, HYDRA_BUFFER_TYPE::HYDRA_SSBO_BUFFER); task_scheduler->WaitForTask(create_gpu_buffer_task_id); } void HydraLightBufferManager::Shutdown() { HydraTaskScheduler *task_scheduler = GetEngine()->TaskScheduler(); HydraID delete_gpu_buffer_task_id = task_scheduler->CreateTask(HydraThreadAffinity::Render); HydraDeleteGPUBufferTask *task = static_cast(task_scheduler->GetTask(delete_gpu_buffer_task_id)); task->Intialise(m_light_buffer_id); task_scheduler->WaitForTask(delete_gpu_buffer_task_id); } void HydraLightBufferManager::UpdateBuffer() { void *buffer = static_cast(m_lights.data()); HydraTaskScheduler *task_scheduler = GetEngine()->TaskScheduler(); HydraID update_buffer_task_id = task_scheduler->CreateTask(HydraThreadAffinity::Render); HydraUpdatePartialGPUBufferTask *task = static_cast(task_scheduler->GetTask(update_buffer_task_id)); task->Intialise(m_light_buffer_id, 0, sizeof(HydraLightComponent) * m_lights.size(), buffer); task_scheduler->WaitForTask(update_buffer_task_id); } void HydraLightBufferManager::AddLight(HydraLightComponent light) { std::lock_guard lock(m_mutex); if(m_available_lights.size() == 0) { return; } auto it = std::find(m_light_lookup.begin(), m_light_lookup.end(), light.entity_id); if(it == m_light_lookup.end()) { //light ID is not the index in the light buffer - this has to stay contiguous m_lights.push_back(light); m_light_lookup[m_light_count] = light.entity_id; m_light_count++; } else { m_lights[m_light_lookup[*it]] = light; } } //Remove the light from the buffer and shuffle all of the others down to keep //the light buffer contiguous. void HydraLightBufferManager::RemoveLight(HydraID entity_id) { std::lock_guard lock(m_mutex); auto it = std::find(m_light_lookup.begin(), m_light_lookup.end(), entity_id); if(it != m_light_lookup.end()) { uint32_t remove_idx = it - m_light_lookup.begin(); //end one - easy if(remove_idx == m_light_count-1) { m_lights.erase(m_lights.end()-1); m_light_count--; return; } HydraLightComponent light_to_delete = m_lights[remove_idx]; HydraLightComponent light_to_move = m_lights[m_light_count-1]; m_lights[remove_idx] = light_to_move; m_lights.erase(m_lights.end()-1); m_light_lookup[m_light_count-1] = INVALID_HYDRA_ID; m_light_lookup[remove_idx] = light_to_move.entity_id; m_light_count--; } } uint32_t HydraLightBufferManager::GetLightCount() { return m_light_count; }