2022-10-03 18:51:34 +05:00
|
|
|
|
|
|
|
#include "device.hpp"
|
|
|
|
#include "opengl/device.hpp"
|
|
|
|
|
|
|
|
|
|
|
|
namespace hpr::gpu
|
|
|
|
{
|
|
|
|
|
2022-10-05 21:10:51 +05:00
|
|
|
Device::Device() :
|
|
|
|
Context {DeviceAPI::Unknown},
|
2022-10-27 22:27:50 +05:00
|
|
|
p_currentVertexBuffer {},
|
|
|
|
p_currentIndexBuffer {},
|
2022-11-18 21:50:49 +05:00
|
|
|
p_currentUniformBuffer {},
|
2022-10-27 22:27:50 +05:00
|
|
|
p_currentShaderProgram {}
|
2022-10-05 21:10:51 +05:00
|
|
|
{}
|
2022-10-03 18:51:34 +05:00
|
|
|
|
2022-10-05 21:10:51 +05:00
|
|
|
Device::Device(DeviceAPI api) :
|
|
|
|
Context {api},
|
2022-10-27 22:27:50 +05:00
|
|
|
p_currentVertexBuffer {},
|
|
|
|
p_currentIndexBuffer {},
|
2022-11-18 21:50:49 +05:00
|
|
|
p_currentUniformBuffer {},
|
2022-10-27 22:27:50 +05:00
|
|
|
p_currentShaderProgram {}
|
2022-10-05 21:10:51 +05:00
|
|
|
{}
|
2022-10-03 18:51:34 +05:00
|
|
|
|
2022-10-05 21:10:51 +05:00
|
|
|
Device::~Device()
|
2022-11-18 21:50:49 +05:00
|
|
|
{
|
|
|
|
for (auto& shader : p_shaders)
|
|
|
|
delete shader;
|
|
|
|
for (auto& buffer : p_buffers)
|
|
|
|
delete buffer;
|
|
|
|
for (auto& shaderProgram : p_shaderPrograms)
|
|
|
|
delete shaderProgram;
|
|
|
|
for (auto& texture : p_textures)
|
|
|
|
delete texture;
|
|
|
|
}
|
2022-10-03 18:51:34 +05:00
|
|
|
|
2022-10-05 21:10:51 +05:00
|
|
|
// Global functions
|
|
|
|
|
|
|
|
void Device::create(Device** device, DeviceAPI api)
|
|
|
|
{
|
|
|
|
if (device == nullptr)
|
2022-10-27 22:27:50 +05:00
|
|
|
throw std::invalid_argument("Invalid parameter 'nullptr'");
|
2022-10-05 21:10:51 +05:00
|
|
|
if (api == DeviceAPI::Unknown)
|
2022-10-27 22:27:50 +05:00
|
|
|
throw std::invalid_argument("Cannot create device for 'Unknown'");
|
2022-10-05 21:10:51 +05:00
|
|
|
|
|
|
|
*device = nullptr;
|
|
|
|
|
|
|
|
if (api == DeviceAPI::OpenGL)
|
|
|
|
*device = new opengl::Device;
|
|
|
|
else
|
2022-10-27 22:27:50 +05:00
|
|
|
throw std::invalid_argument("Unsupported device");
|
2022-10-05 21:10:51 +05:00
|
|
|
}
|
2022-10-03 18:51:34 +05:00
|
|
|
|
2022-11-29 12:52:33 +05:00
|
|
|
// Render targets
|
|
|
|
|
|
|
|
void Device::moveRenderTarget(RenderTarget* target, int x, int y)
|
|
|
|
{
|
|
|
|
if (target == nullptr)
|
|
|
|
throw std::invalid_argument("Invalid parameter");
|
|
|
|
target->p_posX = x;
|
|
|
|
target->p_posY = y;
|
|
|
|
}
|
|
|
|
|
|
|
|
void Device::scaleRenderTarget(RenderTarget* target, int width, int height)
|
|
|
|
{
|
|
|
|
if (target == nullptr)
|
|
|
|
throw std::invalid_argument("Invalid parameter");
|
|
|
|
target->p_width = width;
|
|
|
|
target->p_height = height;
|
|
|
|
}
|
|
|
|
|
|
|
|
void Device::destroyRenderTarget(RenderTarget*& target)
|
|
|
|
{
|
|
|
|
if (!target)
|
|
|
|
throw std::runtime_error("Invalid parameter");
|
|
|
|
|
|
|
|
for (auto iter = p_renderTargets.begin(); iter != p_renderTargets.end(); ++iter)
|
|
|
|
if (*iter == target)
|
|
|
|
{
|
|
|
|
delete target;
|
|
|
|
target = nullptr;
|
|
|
|
p_renderTargets.remove(iter);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-10-05 21:10:51 +05:00
|
|
|
// Buffers
|
|
|
|
|
|
|
|
void Device::useVertexBuffer(Buffer* buffer, int stride, int offset)
|
|
|
|
{
|
|
|
|
if (buffer)
|
|
|
|
{
|
|
|
|
if (buffer->p_type == Buffer::BufferType::Vertex)
|
|
|
|
{
|
|
|
|
p_currentVertexBuffer = buffer;
|
|
|
|
p_currentVertexBuffer->p_stride = stride;
|
|
|
|
}
|
|
|
|
else
|
2022-11-18 21:50:49 +05:00
|
|
|
throw std::runtime_error("Incompatible buffer");
|
2022-10-05 21:10:51 +05:00
|
|
|
}
|
|
|
|
else
|
|
|
|
p_currentVertexBuffer = nullptr;
|
|
|
|
}
|
2022-10-03 18:51:34 +05:00
|
|
|
|
2022-10-05 21:10:51 +05:00
|
|
|
void Device::useIndexBuffer(Buffer* buffer, int offset)
|
|
|
|
{
|
|
|
|
if (buffer)
|
|
|
|
{
|
|
|
|
if (buffer->p_type == Buffer::BufferType::Index)
|
|
|
|
{
|
|
|
|
p_currentIndexBuffer = buffer;
|
|
|
|
}
|
2022-10-03 18:51:34 +05:00
|
|
|
else
|
2022-11-18 21:50:49 +05:00
|
|
|
throw std::runtime_error("Incompatible buffer");
|
2022-10-03 18:51:34 +05:00
|
|
|
}
|
2022-10-05 21:10:51 +05:00
|
|
|
else
|
|
|
|
p_currentIndexBuffer = nullptr;
|
|
|
|
}
|
|
|
|
|
2022-11-18 21:50:49 +05:00
|
|
|
void Device::useUniformBuffer(Buffer* buffer, int slot)
|
|
|
|
{
|
|
|
|
if (buffer)
|
|
|
|
{
|
|
|
|
if (buffer->p_type == Buffer::BufferType::Uniform)
|
|
|
|
p_currentUniformBuffer = buffer;
|
|
|
|
else
|
|
|
|
throw std::runtime_error("Incompatible buffer");
|
|
|
|
}
|
|
|
|
else
|
|
|
|
p_currentUniformBuffer = nullptr;
|
|
|
|
}
|
|
|
|
|
2022-10-05 21:10:51 +05:00
|
|
|
void Device::destroyBuffer(Buffer*& buffer)
|
|
|
|
{
|
|
|
|
if (!buffer)
|
2022-11-18 21:50:49 +05:00
|
|
|
throw std::runtime_error("Invalid parameter");
|
2022-10-05 21:10:51 +05:00
|
|
|
|
|
|
|
for (auto iter = p_buffers.begin(); iter != p_buffers.end(); ++iter)
|
2022-11-18 21:50:49 +05:00
|
|
|
if (*iter == buffer)
|
|
|
|
{
|
|
|
|
delete buffer;
|
|
|
|
buffer = nullptr;
|
|
|
|
p_buffers.remove(iter);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
Buffer* Device::activeBuffer(Buffer::BufferType type)
|
|
|
|
{
|
|
|
|
switch (type)
|
|
|
|
{
|
|
|
|
case Buffer::BufferType::Vertex:
|
|
|
|
return p_currentVertexBuffer;
|
|
|
|
case Buffer::BufferType::Index:
|
|
|
|
return p_currentIndexBuffer;
|
|
|
|
case Buffer::BufferType::Uniform:
|
|
|
|
return p_currentUniformBuffer;
|
|
|
|
default:
|
|
|
|
return nullptr;
|
|
|
|
}
|
2022-10-05 21:10:51 +05:00
|
|
|
}
|
|
|
|
|
|
|
|
// Shaders
|
|
|
|
|
2022-11-18 21:50:49 +05:00
|
|
|
void Device::destroyShader(Shader* shader)
|
2022-10-05 21:10:51 +05:00
|
|
|
{
|
|
|
|
if (shader == nullptr)
|
2022-11-18 21:50:49 +05:00
|
|
|
throw std::runtime_error("Invalid parameter");
|
2022-10-05 21:10:51 +05:00
|
|
|
|
|
|
|
for (auto iter = p_shaders.begin(); iter != p_shaders.end(); ++iter)
|
2022-11-18 21:50:49 +05:00
|
|
|
if (*iter == shader)
|
|
|
|
{
|
|
|
|
delete shader;
|
|
|
|
shader = nullptr;
|
|
|
|
p_shaders.remove(iter);
|
|
|
|
break;
|
|
|
|
}
|
2022-10-05 21:10:51 +05:00
|
|
|
}
|
|
|
|
|
|
|
|
// Shader programs
|
|
|
|
|
|
|
|
void Device::attachShader(ShaderProgram *program, Shader *shader)
|
|
|
|
{
|
|
|
|
if (program == nullptr || shader == nullptr)
|
2022-11-18 21:50:49 +05:00
|
|
|
throw std::runtime_error("Invalid parameter");
|
2022-10-05 21:10:51 +05:00
|
|
|
if (program->p_isLinked)
|
2022-11-18 21:50:49 +05:00
|
|
|
throw std::runtime_error("Shader program already linked");
|
2022-10-05 21:10:51 +05:00
|
|
|
|
|
|
|
program->p_slots[(int)shader->p_type] = shader;
|
|
|
|
}
|
|
|
|
|
|
|
|
void Device::linkProgram(ShaderProgram *program)
|
|
|
|
{
|
|
|
|
if (program == nullptr)
|
2022-11-18 21:50:49 +05:00
|
|
|
throw std::runtime_error("Invalid parameter");
|
2022-10-05 21:10:51 +05:00
|
|
|
if (program->p_isLinked)
|
2022-11-18 21:50:49 +05:00
|
|
|
throw std::runtime_error("Shader program already linked");
|
2022-10-05 21:10:51 +05:00
|
|
|
|
|
|
|
program->p_isLinked = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
void Device::useShaderProgram(ShaderProgram *program)
|
|
|
|
{
|
|
|
|
if (program != nullptr)
|
|
|
|
if (!program->p_isLinked)
|
2022-11-18 21:50:49 +05:00
|
|
|
throw std::runtime_error("Shader program is not linked");
|
2022-10-05 21:10:51 +05:00
|
|
|
|
|
|
|
p_currentShaderProgram = program;
|
|
|
|
}
|
|
|
|
|
|
|
|
void Device::destroyShaderProgram(ShaderProgram *&program, bool withShaders)
|
|
|
|
{
|
|
|
|
if (program == p_currentShaderProgram)
|
|
|
|
useShaderProgram(nullptr);
|
|
|
|
|
|
|
|
if (withShaders)
|
|
|
|
for (size_t n = 0; n < (size_t)Shader::ShaderType::ShaderTypeCount; n++)
|
|
|
|
destroyShader(program->p_slots[n]);
|
2022-11-18 21:50:49 +05:00
|
|
|
|
|
|
|
for (auto iter = p_shaderPrograms.begin(); iter != p_shaderPrograms.end(); ++iter)
|
|
|
|
if (*iter == program)
|
|
|
|
{
|
|
|
|
delete program;
|
|
|
|
program = nullptr;
|
|
|
|
p_shaderPrograms.remove(iter);
|
|
|
|
break;
|
|
|
|
}
|
2022-10-05 21:10:51 +05:00
|
|
|
}
|
|
|
|
|
|
|
|
// Textures
|
|
|
|
|
|
|
|
void Device::destroyTexture(Texture *&texture)
|
|
|
|
{
|
|
|
|
for (auto iter = p_textures.begin(); iter != p_textures.end(); ++iter)
|
2022-11-18 21:50:49 +05:00
|
|
|
if (*iter == texture)
|
|
|
|
{
|
|
|
|
delete texture;
|
|
|
|
texture = nullptr;
|
|
|
|
p_textures.remove(iter);
|
|
|
|
break;
|
|
|
|
}
|
2022-10-05 21:10:51 +05:00
|
|
|
}
|
|
|
|
|
2022-10-03 18:51:34 +05:00
|
|
|
}
|