OpenGLRenderer: Use generic DeviceObject
This commit is contained in:
parent
b4b15f826d
commit
1c23949608
|
|
@ -9,41 +9,43 @@
|
|||
|
||||
#include <Nazara/Prerequisites.hpp>
|
||||
#include <Nazara/Core/MovablePtr.hpp>
|
||||
#include <Nazara/OpenGLRenderer/Wrapper/Context.hpp>
|
||||
#include <string>
|
||||
|
||||
namespace Nz::GL
|
||||
{
|
||||
template<typename C>
|
||||
template<typename C, GLenum ObjectType, typename... CreateArgs>
|
||||
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<OpenGLDevice> m_device;
|
||||
GLuint m_handle;
|
||||
MovableValue<GLuint> m_objectId;
|
||||
};
|
||||
}
|
||||
|
||||
#include <Nazara/OpenGLRenderer/Wrapper/DeviceObject.inl>
|
||||
|
||||
#endif // NAZARA_OPENGLRENDERER_VKDEVICEOBJECT_HPP
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -7,116 +7,88 @@
|
|||
#include <Nazara/OpenGLRenderer/Utils.hpp>
|
||||
#include <Nazara/OpenGLRenderer/Debug.hpp>
|
||||
|
||||
namespace Nz
|
||||
namespace Nz::GL
|
||||
{
|
||||
namespace Vk
|
||||
template<typename C, GLenum ObjectType, typename... CreateArgs>
|
||||
DeviceObject<C, ObjectType, CreateArgs...>::~DeviceObject()
|
||||
{
|
||||
template<typename C, typename VkType, typename CreateInfo, VkObjectType ObjectType>
|
||||
DeviceObject<C, VkType, CreateInfo, ObjectType>::DeviceObject() :
|
||||
m_handle(VK_NULL_HANDLE)
|
||||
Destroy();
|
||||
}
|
||||
|
||||
template<typename C, GLenum ObjectType, typename... CreateArgs>
|
||||
bool DeviceObject<C, ObjectType, CreateArgs...>::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<typename C, typename VkType, typename CreateInfo, VkObjectType ObjectType>
|
||||
DeviceObject<C, VkType, CreateInfo, ObjectType>::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<typename C, GLenum ObjectType, typename... CreateArgs>
|
||||
void DeviceObject<C, ObjectType, CreateArgs...>::Destroy()
|
||||
{
|
||||
if (IsValid())
|
||||
{
|
||||
object.m_handle = VK_NULL_HANDLE;
|
||||
const Context& context = EnsureDeviceContext();
|
||||
|
||||
C::DestroyHelper(*m_device, context, m_objectId);
|
||||
m_objectId = InvalidObject;
|
||||
}
|
||||
}
|
||||
|
||||
template<typename C, GLenum ObjectType, typename... CreateArgs>
|
||||
bool DeviceObject<C, ObjectType, CreateArgs...>::IsValid() const
|
||||
{
|
||||
return m_objectId != InvalidObject;
|
||||
}
|
||||
|
||||
template<typename C, GLenum ObjectType, typename... CreateArgs>
|
||||
OpenGLDevice* DeviceObject<C, ObjectType, CreateArgs...>::GetDevice() const
|
||||
{
|
||||
return m_device;
|
||||
}
|
||||
|
||||
template<typename C, GLenum ObjectType, typename... CreateArgs>
|
||||
GLuint DeviceObject<C, ObjectType, CreateArgs...>::GetObjectId() const
|
||||
{
|
||||
return m_objectId;
|
||||
}
|
||||
|
||||
template<typename C, GLenum ObjectType, typename... CreateArgs>
|
||||
void DeviceObject<C, ObjectType, CreateArgs...>::SetDebugName(const std::string_view& name)
|
||||
{
|
||||
const Context& context = EnsureDeviceContext();
|
||||
|
||||
if (context.glObjectLabel)
|
||||
context.glObjectLabel(ObjectType, m_objectId, name.size(), name.data());
|
||||
}
|
||||
|
||||
template<typename C, GLenum ObjectType, typename... CreateArgs>
|
||||
const Context& DeviceObject<C, ObjectType, CreateArgs...>::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<typename C, typename VkType, typename CreateInfo, VkObjectType ObjectType>
|
||||
DeviceObject<C, VkType, CreateInfo, ObjectType>::~DeviceObject()
|
||||
{
|
||||
Destroy();
|
||||
}
|
||||
|
||||
template<typename C, typename VkType, typename CreateInfo, VkObjectType ObjectType>
|
||||
bool DeviceObject<C, VkType, CreateInfo, ObjectType>::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<typename C, typename VkType, typename CreateInfo, VkObjectType ObjectType>
|
||||
void DeviceObject<C, VkType, CreateInfo, ObjectType>::Destroy()
|
||||
{
|
||||
if (IsValid())
|
||||
{
|
||||
C::DestroyHelper(*m_device, m_handle, (m_allocator.pfnAllocation) ? &m_allocator : nullptr);
|
||||
m_handle = VK_NULL_HANDLE;
|
||||
}
|
||||
}
|
||||
|
||||
template<typename C, typename VkType, typename CreateInfo, VkObjectType ObjectType>
|
||||
bool DeviceObject<C, VkType, CreateInfo, ObjectType>::IsValid() const
|
||||
{
|
||||
return m_handle != VK_NULL_HANDLE;
|
||||
}
|
||||
|
||||
template<typename C, typename VkType, typename CreateInfo, VkObjectType ObjectType>
|
||||
Device* DeviceObject<C, VkType, CreateInfo, ObjectType>::GetDevice() const
|
||||
{
|
||||
return m_device;
|
||||
}
|
||||
|
||||
template<typename C, typename VkType, typename CreateInfo, VkObjectType ObjectType>
|
||||
VkResult DeviceObject<C, VkType, CreateInfo, ObjectType>::GetLastErrorCode() const
|
||||
{
|
||||
return m_lastErrorCode;
|
||||
}
|
||||
|
||||
template<typename C, typename VkType, typename CreateInfo, VkObjectType ObjectType>
|
||||
void DeviceObject<C, VkType, CreateInfo, ObjectType>::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<UInt64>(reinterpret_cast<std::uintptr_t>(m_handle));
|
||||
debugName.pObjectName = name;
|
||||
|
||||
m_device->vkSetDebugUtilsObjectNameEXT(*m_device, &debugName);
|
||||
}
|
||||
}
|
||||
|
||||
template<typename C, typename VkType, typename CreateInfo, VkObjectType ObjectType>
|
||||
void DeviceObject<C, VkType, CreateInfo, ObjectType>::SetDebugName(const std::string& name)
|
||||
{
|
||||
return SetDebugName(name.data());
|
||||
}
|
||||
|
||||
template<typename C, typename VkType, typename CreateInfo, VkObjectType ObjectType>
|
||||
auto DeviceObject<C, VkType, CreateInfo, ObjectType>::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<typename C, typename VkType, typename CreateInfo, VkObjectType ObjectType>
|
||||
DeviceObject<C, VkType, CreateInfo, ObjectType>::operator VkType() const
|
||||
{
|
||||
return m_handle;
|
||||
}
|
||||
return *activeContext;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -10,22 +10,22 @@
|
|||
#include <Nazara/Prerequisites.hpp>
|
||||
#include <Nazara/Core/MovableValue.hpp>
|
||||
#include <Nazara/OpenGLRenderer/OpenGLDevice.hpp>
|
||||
#include <Nazara/OpenGLRenderer/Wrapper/DeviceObject.hpp>
|
||||
|
||||
namespace Nz::GL
|
||||
{
|
||||
class Shader
|
||||
class Shader : public DeviceObject<Shader, GL_SHADER, GLenum>
|
||||
{
|
||||
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<OpenGLDevice> m_device;
|
||||
MovableValue<GLuint> m_shader;
|
||||
static inline GLuint CreateHelper(OpenGLDevice& device, const Context& context, GLenum shaderStage);
|
||||
static inline void DestroyHelper(OpenGLDevice& device, const Context& context, GLuint objectId);
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -10,19 +10,19 @@
|
|||
#include <Nazara/Prerequisites.hpp>
|
||||
#include <Nazara/Core/MovableValue.hpp>
|
||||
#include <Nazara/OpenGLRenderer/OpenGLDevice.hpp>
|
||||
#include <Nazara/OpenGLRenderer/Wrapper/DeviceObject.hpp>
|
||||
|
||||
namespace Nz::GL
|
||||
{
|
||||
class Texture
|
||||
class Texture : public DeviceObject<Texture, GL_TEXTURE>
|
||||
{
|
||||
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<OpenGLDevice> m_device;
|
||||
MovableValue<GLuint> m_texture;
|
||||
static inline GLuint CreateHelper(OpenGLDevice& device, const Context& context);
|
||||
static inline void DestroyHelper(OpenGLDevice& device, const Context& context, GLuint objectId);
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue