diff --git a/include/Nazara/OpenGLRenderer/Wrapper/DeviceObject.hpp b/include/Nazara/OpenGLRenderer/Wrapper/DeviceObject.hpp index 495297289..e9a241ad4 100644 --- a/include/Nazara/OpenGLRenderer/Wrapper/DeviceObject.hpp +++ b/include/Nazara/OpenGLRenderer/Wrapper/DeviceObject.hpp @@ -9,41 +9,43 @@ #include #include +#include #include namespace Nz::GL { - template + template class DeviceObject { public: - DeviceObject(); + DeviceObject() = default; DeviceObject(const DeviceObject&) = delete; - DeviceObject(DeviceObject&& object) noexcept; + DeviceObject(DeviceObject&& object) noexcept = default; ~DeviceObject(); - bool Create(OpenGLDevice& device); + bool Create(OpenGLDevice& device, CreateArgs... args); void Destroy(); bool IsValid() const; - Device* GetDevice() const; - VkResult GetLastErrorCode() const; + OpenGLDevice* GetDevice() const; + GLuint GetObjectId() const; - void SetDebugName(const char* name); - void SetDebugName(const std::string& name); + void SetDebugName(const std::string_view& name); DeviceObject& operator=(const DeviceObject&) = delete; - DeviceObject& operator=(DeviceObject&& object) noexcept; + DeviceObject& operator=(DeviceObject&& object) noexcept = default; - operator VkType() const; + static constexpr GLuint InvalidObject = 0; protected: + const Context& EnsureDeviceContext(); + MovablePtr m_device; - GLuint m_handle; + MovableValue m_objectId; }; } #include -#endif // NAZARA_OPENGLRENDERER_VKDEVICEOBJECT_HPP +#endif diff --git a/include/Nazara/OpenGLRenderer/Wrapper/DeviceObject.inl b/include/Nazara/OpenGLRenderer/Wrapper/DeviceObject.inl index 1dbf21289..08d029c79 100644 --- a/include/Nazara/OpenGLRenderer/Wrapper/DeviceObject.inl +++ b/include/Nazara/OpenGLRenderer/Wrapper/DeviceObject.inl @@ -7,116 +7,88 @@ #include #include -namespace Nz +namespace Nz::GL { - namespace Vk + template + DeviceObject::~DeviceObject() { - template - DeviceObject::DeviceObject() : - m_handle(VK_NULL_HANDLE) + Destroy(); + } + + template + bool DeviceObject::Create(OpenGLDevice& device, CreateArgs... args) + { + Destroy(); + + m_device = &device; + + const Context& context = EnsureDeviceContext(); + + m_objectId = C::CreateHelper(*m_device, context, args...); + if (m_objectId == InvalidObject) { + NazaraError("Failed to create OpenGL object"); //< TODO: Handle error message + return false; } - template - DeviceObject::DeviceObject(DeviceObject&& object) noexcept : - m_device(std::move(object.m_device)), - m_allocator(object.m_allocator), - m_handle(object.m_handle), - m_lastErrorCode(object.m_lastErrorCode) + return true; + } + + template + void DeviceObject::Destroy() + { + if (IsValid()) { - object.m_handle = VK_NULL_HANDLE; + const Context& context = EnsureDeviceContext(); + + C::DestroyHelper(*m_device, context, m_objectId); + m_objectId = InvalidObject; + } + } + + template + bool DeviceObject::IsValid() const + { + return m_objectId != InvalidObject; + } + + template + OpenGLDevice* DeviceObject::GetDevice() const + { + return m_device; + } + + template + GLuint DeviceObject::GetObjectId() const + { + return m_objectId; + } + + template + void DeviceObject::SetDebugName(const std::string_view& name) + { + const Context& context = EnsureDeviceContext(); + + if (context.glObjectLabel) + context.glObjectLabel(ObjectType, m_objectId, name.size(), name.data()); + } + + template + const Context& DeviceObject::EnsureDeviceContext() + { + assert(m_device); + + const Context* activeContext = Context::GetCurrentContext(); + if (!activeContext || activeContext->GetDevice() != m_device) + { + const Context& referenceContext = m_device->GetReferenceContext(); + if (!Context::SetCurrentContext(&referenceContext)) + throw std::runtime_error("failed to activate context"); + + return referenceContext; } - template - DeviceObject::~DeviceObject() - { - Destroy(); - } - - template - bool DeviceObject::Create(Device& device, const CreateInfo& createInfo, const VkAllocationCallbacks* allocator) - { - m_device = &device; - m_lastErrorCode = C::CreateHelper(*m_device, &createInfo, allocator, &m_handle); - if (m_lastErrorCode != VkResult::VK_SUCCESS) - { - NazaraError("Failed to create OpenGL object: " + TranslateOpenGLError(m_lastErrorCode)); - return false; - } - - // Store the allocator to access them when needed - if (allocator) - m_allocator = *allocator; - else - m_allocator.pfnAllocation = nullptr; - - return true; - } - - template - void DeviceObject::Destroy() - { - if (IsValid()) - { - C::DestroyHelper(*m_device, m_handle, (m_allocator.pfnAllocation) ? &m_allocator : nullptr); - m_handle = VK_NULL_HANDLE; - } - } - - template - bool DeviceObject::IsValid() const - { - return m_handle != VK_NULL_HANDLE; - } - - template - Device* DeviceObject::GetDevice() const - { - return m_device; - } - - template - VkResult DeviceObject::GetLastErrorCode() const - { - return m_lastErrorCode; - } - - template - void DeviceObject::SetDebugName(const char* name) - { - if (m_device->vkSetDebugUtilsObjectNameEXT) - { - VkDebugUtilsObjectNameInfoEXT debugName = { VK_STRUCTURE_TYPE_DEBUG_UTILS_OBJECT_NAME_INFO_EXT }; - debugName.objectType = ObjectType; - debugName.objectHandle = static_cast(reinterpret_cast(m_handle)); - debugName.pObjectName = name; - - m_device->vkSetDebugUtilsObjectNameEXT(*m_device, &debugName); - } - } - - template - void DeviceObject::SetDebugName(const std::string& name) - { - return SetDebugName(name.data()); - } - - template - auto DeviceObject::operator=(DeviceObject&& object) noexcept -> DeviceObject& - { - std::swap(m_allocator, object.m_allocator); - std::swap(m_device, object.m_device); - std::swap(m_handle, object.m_handle); - std::swap(m_lastErrorCode, object.m_lastErrorCode); - - return *this; - } - - template - DeviceObject::operator VkType() const - { - return m_handle; - } + return *activeContext; } } diff --git a/include/Nazara/OpenGLRenderer/Wrapper/Shader.hpp b/include/Nazara/OpenGLRenderer/Wrapper/Shader.hpp index 13eda392b..b99e752fa 100644 --- a/include/Nazara/OpenGLRenderer/Wrapper/Shader.hpp +++ b/include/Nazara/OpenGLRenderer/Wrapper/Shader.hpp @@ -10,22 +10,22 @@ #include #include #include +#include namespace Nz::GL { - class Shader + class Shader : public DeviceObject { + friend DeviceObject; + public: Shader() = default; Shader(const Shader&) = delete; Shader(Shader&&) noexcept = default; - inline ~Shader(); + ~Shader() = default; inline void Compile(); - inline bool Create(OpenGLDevice& device, GLenum type); - inline void Destroy(); - inline bool GetCompilationStatus(std::string* error = nullptr); inline void SetBinarySource(GLenum binaryFormat, const void* binary, GLsizei length); @@ -38,8 +38,8 @@ namespace Nz::GL Shader& operator=(Shader&&) noexcept = default; private: - MovablePtr m_device; - MovableValue m_shader; + static inline GLuint CreateHelper(OpenGLDevice& device, const Context& context, GLenum shaderStage); + static inline void DestroyHelper(OpenGLDevice& device, const Context& context, GLuint objectId); }; } diff --git a/include/Nazara/OpenGLRenderer/Wrapper/Shader.inl b/include/Nazara/OpenGLRenderer/Wrapper/Shader.inl index e7a5e4f11..ee6ebf850 100644 --- a/include/Nazara/OpenGLRenderer/Wrapper/Shader.inl +++ b/include/Nazara/OpenGLRenderer/Wrapper/Shader.inl @@ -8,58 +8,32 @@ namespace Nz::GL { - inline Shader::~Shader() - { - Destroy(); - } - inline void Shader::Compile() { - assert(m_shader); - m_device->GetReferenceContext().glCompileShader(m_shader); - } - - inline bool Shader::Create(OpenGLDevice& device, GLenum type) - { - Destroy(); - - m_device = &device; - m_shader = device.GetReferenceContext().glCreateShader(type); - if (!m_shader) - return false; //< TODO: Handle error messages - - return true; - } - - inline void Shader::Destroy() - { - if (m_shader) - { - m_device->GetReferenceContext().glDeleteShader(m_shader); - m_shader = 0; - } + assert(m_objectId); + m_device->GetReferenceContext().glCompileShader(m_objectId); } inline bool Shader::GetCompilationStatus(std::string* error) { - assert(m_shader); - const GL::Context& context = m_device->GetReferenceContext(); + assert(m_objectId); + const Context& context = EnsureDeviceContext(); GLint success; - context.glGetShaderiv(m_shader, GL_COMPILE_STATUS, &success); + context.glGetShaderiv(m_objectId, GL_COMPILE_STATUS, &success); if (!success) { if (error) { GLint logLength; - context.glGetShaderiv(m_shader, GL_INFO_LOG_LENGTH, &logLength); + context.glGetShaderiv(m_objectId, GL_INFO_LOG_LENGTH, &logLength); error->resize(logLength); if (logLength > 0) { GLsizei dummy; - context.glGetShaderInfoLog(m_shader, logLength, &dummy, error->data()); + context.glGetShaderInfoLog(m_objectId, logLength, &dummy, error->data()); } } @@ -71,25 +45,35 @@ namespace Nz::GL inline void Shader::SetBinarySource(GLenum binaryFormat, const void* binary, GLsizei length) { - assert(m_shader); + assert(m_objectId); - m_device->GetReferenceContext().glShaderBinary(1U, &m_shader.Get(), binaryFormat, binary, length); + m_device->GetReferenceContext().glShaderBinary(1U, &m_objectId.Get(), binaryFormat, binary, length); } inline void Shader::SetSource(const char* source, GLint length) { - assert(m_shader); + assert(m_objectId); - m_device->GetReferenceContext().glShaderSource(m_shader, 1U, &source, &length); + m_device->GetReferenceContext().glShaderSource(m_objectId, 1U, &source, &length); } inline void Shader::SpecializeShader(const GLchar* pEntryPoint, GLuint numSpecializationConstants, const GLuint* pConstantIndex, const GLuint* pConstantValue) { - assert(m_shader); - const GL::Context& context = m_device->GetReferenceContext(); + assert(m_objectId); + const Context& context = EnsureDeviceContext(); assert(context.glSpecializeShaderARB); - context.glSpecializeShaderARB(m_shader, pEntryPoint, numSpecializationConstants, pConstantIndex, pConstantValue); + context.glSpecializeShaderARB(m_objectId, pEntryPoint, numSpecializationConstants, pConstantIndex, pConstantValue); + } + + inline GLuint Shader::CreateHelper(OpenGLDevice& device, const Context& context, GLenum shaderStage) + { + return context.glCreateShader(shaderStage); + } + + inline void Shader::DestroyHelper(OpenGLDevice& device, const Context& context, GLuint objectId) + { + context.glDeleteShader(objectId); } } diff --git a/include/Nazara/OpenGLRenderer/Wrapper/Texture.hpp b/include/Nazara/OpenGLRenderer/Wrapper/Texture.hpp index af71a484b..1e6198146 100644 --- a/include/Nazara/OpenGLRenderer/Wrapper/Texture.hpp +++ b/include/Nazara/OpenGLRenderer/Wrapper/Texture.hpp @@ -10,19 +10,19 @@ #include #include #include +#include namespace Nz::GL { - class Texture + class Texture : public DeviceObject { + friend DeviceObject; + public: Texture() = default; Texture(const Texture&) = delete; Texture(Texture&&) noexcept = default; - inline ~Texture(); - - inline bool Create(OpenGLDevice& device); - inline void Destroy(); + ~Texture() = default; inline void TexImage2D(GLint level, GLint internalFormat, GLsizei width, GLsizei height, GLint border); inline void TexImage2D(GLint level, GLint internalFormat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const void* data); @@ -32,10 +32,8 @@ namespace Nz::GL Texture& operator=(Texture&&) noexcept = default; private: - const Context& EnsureDeviceContext(); - - MovablePtr m_device; - MovableValue m_texture; + static inline GLuint CreateHelper(OpenGLDevice& device, const Context& context); + static inline void DestroyHelper(OpenGLDevice& device, const Context& context, GLuint objectId); }; } diff --git a/include/Nazara/OpenGLRenderer/Wrapper/Texture.inl b/include/Nazara/OpenGLRenderer/Wrapper/Texture.inl index 3d50a8997..14ef42866 100644 --- a/include/Nazara/OpenGLRenderer/Wrapper/Texture.inl +++ b/include/Nazara/OpenGLRenderer/Wrapper/Texture.inl @@ -8,38 +8,6 @@ namespace Nz::GL { - inline Texture::~Texture() - { - Destroy(); - } - - inline bool Texture::Create(OpenGLDevice& device) - { - Destroy(); - - m_device = &device; - - const Context& context = EnsureDeviceContext(); - context.glGenTextures(1U, &m_texture.Get()); - if (!m_texture) - return false; //< TODO: Handle error messages - - return true; - } - - inline void Texture::Destroy() - { - if (m_texture) - { - const Context& context = EnsureDeviceContext(); - context.glDeleteTextures(1U, &m_texture.Get()); - - m_device->NotifyTextureDestruction(m_texture); - - m_texture = 0; - } - } - inline void Texture::TexImage2D(GLint level, GLint internalFormat, GLsizei width, GLsizei height, GLint border) { return TexImage2D(level, internalFormat, width, height, border, GL_RGB, GL_UNSIGNED_BYTE, nullptr); @@ -48,7 +16,7 @@ namespace Nz::GL inline void Texture::TexImage2D(GLint level, GLint internalFormat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const void* data) { const Context& context = EnsureDeviceContext(); - context.BindTexture(TextureTarget::Target2D, m_texture); + context.BindTexture(TextureTarget::Target2D, m_objectId); context.glTexImage2D(GL_TEXTURE_2D, level, internalFormat, width, height, border, format, type, data); //< TODO: Handle errors @@ -57,27 +25,25 @@ namespace Nz::GL inline void Texture::TexSubImage2D(GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const void* data) { const Context& context = EnsureDeviceContext(); - context.BindTexture(TextureTarget::Target2D, m_texture); + context.BindTexture(TextureTarget::Target2D, m_objectId); context.glTexSubImage2D(GL_TEXTURE_2D, level, xoffset, yoffset, width, height, format, type, data); //< TODO: Handle errors } - inline const Context& Texture::EnsureDeviceContext() + inline GLuint Texture::CreateHelper(OpenGLDevice& device, const Context& context) { - assert(m_device); + GLuint sampler = 0; + context.glGenTextures(1U, &sampler); - const Context* activeContext = Context::GetCurrentContext(); - if (!activeContext || activeContext->GetDevice() != m_device) - { - const Context& referenceContext = m_device->GetReferenceContext(); - if (!Context::SetCurrentContext(&referenceContext)) - throw std::runtime_error("failed to activate context"); + return sampler; + } - return referenceContext; - } + inline void Texture::DestroyHelper(OpenGLDevice& device, const Context& context, GLuint objectId) + { + context.glDeleteTextures(1U, &objectId); - return *activeContext; + device.NotifyTextureDestruction(objectId); } }