Files
HydraV3/HydraEngine/source/buffer/HydraTextureBufferManager.cpp
T

231 lines
7.6 KiB
C++
Raw Normal View History

2026-07-17 15:30:29 +01:00
#define STB_IMAGE_IMPLEMENTATION
#include "HydraTextureBufferManager.h"
#include "../scheduler/HydraTaskScheduler.h"
#include "../task/buffer/HydraCreateTextureTask.hpp"
void HydraTextureBufferManager::Intialise()
{
m_textures.resize(MAX_TEXTURES);
m_bindless_texture_ids.resize(MAX_TEXTURES);
for (uint32_t tex_idx = 0; tex_idx < MAX_TEXTURES; tex_idx++)
{
m_available_texture_ids.push(tex_idx);
m_bindless_texture_ids[tex_idx] = 0;
}
}
void HydraTextureBufferManager::Shutdown()
{
for (uint32_t tex_idx = 0; tex_idx < MAX_TEXTURES; tex_idx++)
{
if (m_textures[tex_idx].texture_id != INVALID_HYDRA_ID)
{
DeleteTexture(tex_idx);
}
}
}
HydraID HydraTextureBufferManager::LoadTexture(std::string texture_filename)
{
HydraID texture_id = FindTexture(texture_filename);
if (texture_id != INVALID_HYDRA_ID)
{
return texture_id;
}
void *data = nullptr;
int width = 0;
int height = 0;
int channels = 0;
//stbi_set_flip_vertically_on_load(true);
data = stbi_load(texture_filename.c_str(), &width, &height, &channels, 0);
if (data == nullptr)
{
return INVALID_HYDRA_ID;
}
uint32_t format = GL_RGBA;
if (channels == 3)
{
format = GL_RGB;
}
HydraTaskScheduler *scheduler = GetEngine()->TaskScheduler();
HydraID create_tex_id = scheduler->CreateTask<HydraCreateTextureTask>(HydraThreadAffinity::Render);
HydraCreateTextureTask *create_tex_task = static_cast<HydraCreateTextureTask *>(scheduler->GetTask(create_tex_id));
HydraID tex_id = INVALID_HYDRA_ID;
2026-07-28 19:02:45 +01:00
create_tex_task->Initialise(texture_filename,
2026-07-17 15:30:29 +01:00
width,
height,
GL_RGBA8,
format,
GL_NEAREST_MIPMAP_NEAREST,
2026-08-04 17:39:07 +01:00
GL_LINEAR,
2026-07-17 15:30:29 +01:00
GL_UNSIGNED_BYTE,
5,
data,
&tex_id);
scheduler->WaitForTask(create_tex_id);
return tex_id;
}
HydraID HydraTextureBufferManager::FindTexture(std::string texture_name)
{
if (m_texture_lookup.find(texture_name) == m_texture_lookup.end())
{
return INVALID_HYDRA_ID;
}
return m_texture_lookup.find(texture_name)->second;
}
void *HydraTextureBufferManager::GetTextureBuffer()
{
return &m_bindless_texture_ids[0];
}
const HydraTextureBuffer &HydraTextureBufferManager::GetTexture(HydraID texture_id)
{
return m_textures[texture_id];
}
HydraID HydraTextureBufferManager::_GetTextureID()
{
std::lock_guard<std::mutex> lock(m_mutex);
if (m_available_texture_ids.size() == 0)
{
return INVALID_HYDRA_ID;
}
HydraID id = m_available_texture_ids.front();
m_available_texture_ids.pop();
return id;
}
2026-07-28 19:02:45 +01:00
HydraID HydraTextureBufferManager::CreateTextureArray(std::string texture_name,
uint32_t width,
uint32_t height,
uint32_t internal_format,
uint32_t min_filter,
uint32_t mag_filter,
uint32_t levels
)
{
uint32_t gl_tex_id = 0;
glCreateTextures(GL_TEXTURE_2D_ARRAY, 1, &gl_tex_id);
glBindTexture(GL_TEXTURE_2D_ARRAY, gl_tex_id);
glTextureStorage3D(gl_tex_id, 1, internal_format, width, height, levels);
glTextureParameteri(gl_tex_id, GL_TEXTURE_MIN_FILTER, min_filter);
glTextureParameteri(gl_tex_id, GL_TEXTURE_MAG_FILTER, mag_filter);
glBindTexture(GL_TEXTURE_2D_ARRAY, 0);
HydraTextureBuffer texture_buffer = {};
HydraID texture_id = _GetTextureID();
texture_buffer.texture_id = texture_id;
texture_buffer.format = 0;
texture_buffer.internal_format = internal_format;
texture_buffer.width = width;
texture_buffer.height = height;
texture_buffer.gl_tex_id = gl_tex_id;
texture_buffer.mag_filter = mag_filter;
texture_buffer.min_filter = min_filter;
m_textures[texture_id] = texture_buffer;
m_texture_lookup.insert(std::pair<std::string, HydraID>(texture_name, texture_id));
return texture_id;
}
HydraID HydraTextureBufferManager::CreateTexture(std::string texture_name,
2026-07-17 15:30:29 +01:00
uint32_t width,
uint32_t height,
uint32_t internal_format,
uint32_t min_filter,
2026-08-04 17:39:07 +01:00
uint32_t mag_filter,
2026-07-17 15:30:29 +01:00
uint32_t format,
uint32_t data_type,
uint32_t mip_levels,
void *data)
{
uint32_t gl_tex_id = 0;
glCreateTextures(GL_TEXTURE_2D, 1, &gl_tex_id);
glBindTexture(GL_TEXTURE_2D, gl_tex_id);
2026-07-28 00:26:04 +01:00
2026-08-04 17:39:07 +01:00
glTextureStorage2D(gl_tex_id,1+ mip_levels, internal_format, width, height);
2026-07-17 15:30:29 +01:00
if (data != nullptr)
{
glTextureSubImage2D(
gl_tex_id,
// level, xoffset, yoffset, width, height
0, 0, 0, width, height,
format, data_type,
data);
if (mip_levels > 0)
{
glGenerateTextureMipmap(gl_tex_id);
}
}
glTextureParameteri(gl_tex_id, GL_TEXTURE_MIN_FILTER, min_filter);
glTextureParameteri(gl_tex_id, GL_TEXTURE_MAG_FILTER, mag_filter);
glBindTexture(GL_TEXTURE_2D, 0);
HydraTextureBuffer texture_buffer = {};
HydraID texture_id = _GetTextureID();
texture_buffer.texture_id = texture_id;
texture_buffer.format = format;
texture_buffer.internal_format = internal_format;
texture_buffer.width = width;
texture_buffer.height = height;
texture_buffer.gl_tex_id = gl_tex_id;
texture_buffer.mag_filter = mag_filter;
texture_buffer.min_filter = min_filter;
m_textures[texture_id] = texture_buffer;
m_texture_lookup.insert(std::pair<std::string, HydraID>(texture_name, texture_id));
return texture_id;
}
2026-07-28 19:02:45 +01:00
void HydraTextureBufferManager::BindTexture(HydraID texture_id, uint32_t target)
2026-07-17 15:30:29 +01:00
{
if (texture_id >= MAX_TEXTURES)
{
return;
}
HydraTextureBuffer texture = m_textures[texture_id];
2026-07-28 19:02:45 +01:00
glBindTexture(target, texture.gl_tex_id);
2026-07-17 15:30:29 +01:00
glTextureParameteri(texture.gl_tex_id, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTextureParameteri(texture.gl_tex_id, GL_TEXTURE_WRAP_T, GL_REPEAT);
glTextureParameteri(texture.gl_tex_id, GL_TEXTURE_MIN_FILTER, texture.min_filter);
glTextureParameteri(texture.gl_tex_id, GL_TEXTURE_MAG_FILTER, texture.mag_filter);
texture.texture_binding = glGetTextureHandleARB(texture.gl_tex_id);
glMakeTextureHandleResidentARB(texture.texture_binding);
m_bindless_texture_ids[texture_id] = texture.texture_binding;
}
void HydraTextureBufferManager::UnbindTexture(HydraID texture_id)
{
glMakeTextureHandleNonResidentARB(texture_id);
}
void HydraTextureBufferManager::DeleteTexture(HydraID texture_id)
{
if (m_bindless_texture_ids[texture_id] != 0)
{
UnbindTexture(m_bindless_texture_ids[texture_id]);
}
}