234 lines
7.7 KiB
C++
234 lines
7.7 KiB
C++
#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;
|
|
create_tex_task->Initialise(texture_filename,
|
|
width,
|
|
height,
|
|
GL_RGBA8,
|
|
format,
|
|
GL_NEAREST_MIPMAP_NEAREST,
|
|
GL_LINEAR,
|
|
1,
|
|
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;
|
|
}
|
|
|
|
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,
|
|
uint32_t width,
|
|
uint32_t height,
|
|
uint32_t internal_format,
|
|
uint32_t min_filter,
|
|
uint32_t mag_filter,
|
|
uint32_t levels,
|
|
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);
|
|
|
|
|
|
glTextureStorage2D(gl_tex_id, levels, internal_format, width, height);
|
|
|
|
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;
|
|
}
|
|
|
|
void HydraTextureBufferManager::BindTexture(HydraID texture_id, uint32_t target)
|
|
{
|
|
|
|
if (texture_id >= MAX_TEXTURES)
|
|
{
|
|
return;
|
|
}
|
|
HydraTextureBuffer texture = m_textures[texture_id];
|
|
glBindTexture(target, texture.gl_tex_id);
|
|
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]);
|
|
}
|
|
}
|