initial commit
This commit is contained in:
@@ -0,0 +1,193 @@
|
||||
#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,
|
||||
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::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 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);
|
||||
|
||||
// important to create mip_levels + 1 images
|
||||
glTextureStorage2D(gl_tex_id, mip_levels + 1, 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)
|
||||
{
|
||||
|
||||
if (texture_id >= MAX_TEXTURES)
|
||||
{
|
||||
return;
|
||||
}
|
||||
HydraTextureBuffer texture = m_textures[texture_id];
|
||||
glBindTexture(GL_TEXTURE_2D, 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]);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user