From eafecd081ded132545120732fc8238fc9026dfe3 Mon Sep 17 00:00:00 2001 From: Rafal Maziejuk Date: Sat, 1 Jun 2024 14:29:28 +0200 Subject: [PATCH] [NOX-76] add GLBuffer unit tests Signed-off-by: Rafal Maziejuk --- include/nox/buffer.h | 1 + include/nox/format.h | 2 - include/nox/texture.h | 1 + src/opengl/gl_buffer.cpp | 61 ++++++----- src/opengl/gl_buffer.h | 26 ++--- src/opengl/gl_command_list.cpp | 14 ++- src/opengl/gl_renderer.cpp | 19 +--- src/opengl/gl_swapchain.cpp | 114 ++++++++++++-------- src/opengl/gl_swapchain.h | 25 +++-- src/opengl/gl_texture.cpp | 7 +- src/opengl/gl_texture.h | 8 +- src/opengl/gl_vertex_array.cpp | 89 ++++++--------- src/opengl/gl_vertex_array.h | 33 +++--- tests/unit_tests/opengl/CMakeLists.txt | 1 + tests/unit_tests/opengl/gl_buffer_tests.cpp | 8 ++ 15 files changed, 205 insertions(+), 204 deletions(-) create mode 100644 tests/unit_tests/opengl/gl_buffer_tests.cpp diff --git a/include/nox/buffer.h b/include/nox/buffer.h index a6ed9436..e952fc12 100644 --- a/include/nox/buffer.h +++ b/include/nox/buffer.h @@ -4,6 +4,7 @@ #include #include +#include namespace nox { diff --git a/include/nox/format.h b/include/nox/format.h index 9438149c..1ea41c6d 100644 --- a/include/nox/format.h +++ b/include/nox/format.h @@ -1,7 +1,5 @@ #pragma once -#include - namespace nox { enum class ImageFormat { diff --git a/include/nox/texture.h b/include/nox/texture.h index 5af8aaec..a0171a00 100644 --- a/include/nox/texture.h +++ b/include/nox/texture.h @@ -40,6 +40,7 @@ class NOX_EXPORT Texture { [[nodiscard]] virtual TextureType getType() const = 0; [[nodiscard]] virtual ImageFormat getFormat() const = 0; + [[nodiscard]] virtual Vector3D getSize() const = 0; public: Texture(const Texture &) = delete; diff --git a/src/opengl/gl_buffer.cpp b/src/opengl/gl_buffer.cpp index c64cf153..5b55862d 100644 --- a/src/opengl/gl_buffer.cpp +++ b/src/opengl/gl_buffer.cpp @@ -4,8 +4,7 @@ #include "opengl/gl_vertex_array.h" #include - -#include +#include "gl_buffer.h" namespace nox { @@ -32,60 +31,60 @@ GLenum mapVertexAttributeTypeToEnum(VertexAttributeType type) { default: break; } - NOX_ASSERT(false); return GL_NONE; } } // namespace -bool GLBuffer::validateInput(const BufferDescriptor &descriptor) { - bool result = true; - - result &= (descriptor.size > 0u); - result &= (descriptor.data != nullptr); - - return result; -} - GLBuffer::GLBuffer(const BufferDescriptor &descriptor) { auto flags = mapBufferUsageToBitfield(descriptor.usage); glCreateBuffers(1, &m_handle); - glNamedBufferStorage(m_handle, descriptor.size, descriptor.data, flags); + + constexpr auto immutableStorageBuffer = true; + if constexpr (immutableStorageBuffer) { + allocateImmutableStorage(descriptor.size, descriptor.data, flags); + } } GLBuffer::~GLBuffer() { glDeleteBuffers(1, &m_handle); } -bool GLVertexBuffer::validateInput(const VertexBufferDescriptor &descriptor) { - bool result = true; +void GLBuffer::allocateImmutableStorage(uint32_t size, const void *data, uint32_t flags) { + glNamedBufferStorage(m_handle, size, data, flags); +} - result &= GLBuffer::validateInput(descriptor); - result &= (!descriptor.vertexAttributes.empty()); +std::unique_ptr GLVertexBuffer::create(const VertexBufferDescriptor &descriptor, GLVertexArrayRegistry ®istry) { + auto buffer = std::make_unique(descriptor, registry); + NOX_ENSURE_RETURN_NULLPTR(buffer->getHandle() != 0u); - return result; + return buffer; } -GLVertexBuffer::~GLVertexBuffer() { - auto &vertexArrayRegistry = GLVertexArrayRegistry::instance(); - vertexArrayRegistry.unregisterVertexArray(m_vertexArrayIndex); +GLVertexBuffer::GLVertexBuffer(const VertexBufferDescriptor &descriptor, GLVertexArrayRegistry ®istry) + : GLBuffer{descriptor}, + m_rVertexArrayRegistry{registry}, + m_vertexAttributes{descriptor.vertexAttributes} { + m_rVertexArrayRegistry.registerVertexArray(m_vertexAttributes); + auto &vertexArray = registry.getVertexArray(m_vertexAttributes); + vertexArray.setVertexBuffer(getHandle()); } -void GLVertexBuffer::setVertexArrayIndex(uint32_t index) { - m_vertexArrayIndex = index; +GLVertexBuffer::~GLVertexBuffer() { + m_rVertexArrayRegistry.unregisterVertexArray(m_vertexAttributes); } -bool GLIndexBuffer::validateInput(const IndexBufferDescriptor &descriptor) { - bool result = true; - - result &= GLBuffer::validateInput(descriptor); +std::unique_ptr GLIndexBuffer::create(const IndexBufferDescriptor &descriptor) { + auto buffer = std::make_unique(descriptor); + NOX_ENSURE_RETURN_NULLPTR(buffer->getHandle() != 0u); - return result; + return buffer; } -void GLIndexBuffer::setIndexType(VertexAttributeFormat format) { - auto descriptor = getVertexAttributeFormatDescriptor(format); - m_indexType = mapVertexAttributeTypeToEnum(descriptor.vertexAttributeType); +GLIndexBuffer::GLIndexBuffer(const IndexBufferDescriptor &descriptor) + : GLBuffer{descriptor} { + auto formatDescriptor = getVertexAttributeFormatDescriptor(descriptor.format); + m_indexType = mapVertexAttributeTypeToEnum(formatDescriptor.vertexAttributeType); } } // namespace nox diff --git a/src/opengl/gl_buffer.h b/src/opengl/gl_buffer.h index 46e0e42c..e7690066 100644 --- a/src/opengl/gl_buffer.h +++ b/src/opengl/gl_buffer.h @@ -1,11 +1,13 @@ #pragma once -#include "opengl/gl_state.h" - #include +#include + namespace nox { +class GLVertexArrayRegistry; + class GLBuffer : public Buffer { public: explicit GLBuffer(const BufferDescriptor &descriptor); @@ -14,7 +16,7 @@ class GLBuffer : public Buffer { [[nodiscard]] uint32_t getHandle() const { return m_handle; } protected: - [[nodiscard]] static bool validateInput(const BufferDescriptor &descriptor); + void allocateImmutableStorage(uint32_t size, const void *data, uint32_t flags); private: uint32_t m_handle{0u}; @@ -22,27 +24,27 @@ class GLBuffer : public Buffer { class GLVertexBuffer final : public GLBuffer { public: - [[nodiscard]] static bool validateInput(const VertexBufferDescriptor &descriptor); + [[nodiscard]] static std::unique_ptr create(const VertexBufferDescriptor &descriptor, + GLVertexArrayRegistry ®istry); - using GLBuffer::GLBuffer; + GLVertexBuffer(const VertexBufferDescriptor &descriptor, GLVertexArrayRegistry ®istry); ~GLVertexBuffer() override; - void setVertexArrayIndex(uint32_t index); - [[nodiscard]] uint32_t getVertexArrayIndex() const { - return m_vertexArrayIndex; + [[nodiscard]] const VertexAttributes &getVertexAttributes() const { + return m_vertexAttributes; } private: - uint32_t m_vertexArrayIndex{0u}; + GLVertexArrayRegistry &m_rVertexArrayRegistry; + VertexAttributes m_vertexAttributes; }; class GLIndexBuffer final : public GLBuffer { public: - [[nodiscard]] static bool validateInput(const IndexBufferDescriptor &descriptor); + [[nodiscard]] static std::unique_ptr create(const IndexBufferDescriptor &descriptor); - using GLBuffer::GLBuffer; + explicit GLIndexBuffer(const IndexBufferDescriptor &descriptor); - void setIndexType(VertexAttributeFormat format); [[nodiscard]] uint32_t getIndexType() const { return m_indexType; } diff --git a/src/opengl/gl_command_list.cpp b/src/opengl/gl_command_list.cpp index 7292da55..3029eaf7 100644 --- a/src/opengl/gl_command_list.cpp +++ b/src/opengl/gl_command_list.cpp @@ -78,12 +78,12 @@ void GLCommandList::bindGraphicsPipelineState(const GraphicsPipelineState &pipel void GLCommandList::bindVertexBuffer(const Buffer &buffer) { const auto *vertexBuffer = static_cast(&buffer); - auto vertexArrayIndex = vertexBuffer->getVertexArrayIndex(); + const auto &vertexAttributes = vertexBuffer->getVertexAttributes(); - auto &vertexArrayRegistry = GLVertexArrayRegistry::instance(); - vertexArrayRegistry.setBoundVertexArrayIndex(vertexArrayIndex); + auto ®istry = GLVertexArrayRegistry::instance(); + registry.setBoundVertexArray(vertexAttributes); - const auto &vertexArray = vertexArrayRegistry.getVertexArray(vertexArrayIndex); + const auto &vertexArray = registry.getBoundVertexArray(); vertexArray.bind(); } @@ -91,10 +91,8 @@ void GLCommandList::bindIndexBuffer(const Buffer &buffer) { const auto *indexBuffer = static_cast(&buffer); m_state.indexType = indexBuffer->getIndexType(); - auto &vertexArrayRegistry = GLVertexArrayRegistry::instance(); - auto vertexArrayIndex = vertexArrayRegistry.getBoundVertexArrayIndex(); - - auto &vertexArray = vertexArrayRegistry.getVertexArray(vertexArrayIndex); + auto ®istry = GLVertexArrayRegistry::instance(); + auto &vertexArray = registry.getBoundVertexArray(); vertexArray.setIndexBuffer(indexBuffer->getHandle()); } diff --git a/src/opengl/gl_renderer.cpp b/src/opengl/gl_renderer.cpp index 7ad4dae2..8dcc4d41 100644 --- a/src/opengl/gl_renderer.cpp +++ b/src/opengl/gl_renderer.cpp @@ -22,31 +22,22 @@ std::unique_ptr GLRenderer::createSwapchain(const SwapchainDescriptor auto context = GLContext::create(descriptor.surfaceDescriptor); NOX_ENSURE_RETURN_NULLPTR_MSG(context != nullptr, "Couldn't create context"); - auto swapchain = GLSwapchain::create(descriptor, std::move(context)); + auto swapchain = GLSwapchain::create(descriptor, std::move(context), GLVertexArrayRegistry::instance()); NOX_ENSURE_RETURN_NULLPTR_MSG(swapchain != nullptr, "Couldn't create swapchain"); return swapchain; } std::unique_ptr GLRenderer::createVertexBuffer(const VertexBufferDescriptor &descriptor) { - NOX_ASSERT(GLVertexBuffer::validateInput(descriptor)); - - auto &vertexArrayRegistry = GLVertexArrayRegistry::instance(); - auto vertexArrayIndex = vertexArrayRegistry.registerVertexArray(descriptor.vertexAttributes); - auto &vertexArray = vertexArrayRegistry.getVertexArray(vertexArrayIndex); - - auto buffer = std::make_unique(descriptor); - buffer->setVertexArrayIndex(vertexArrayIndex); - vertexArray.setVertexBuffer(buffer->getHandle()); + auto buffer = GLVertexBuffer::create(descriptor, GLVertexArrayRegistry::instance()); + NOX_ENSURE_RETURN_NULLPTR_MSG(buffer != nullptr, "Couldn't create vertex buffer"); return buffer; } std::unique_ptr GLRenderer::createIndexBuffer(const IndexBufferDescriptor &descriptor) { - NOX_ASSERT(GLIndexBuffer::validateInput(descriptor)); - - auto buffer = std::make_unique(descriptor); - buffer->setIndexType(descriptor.format); + auto buffer = GLIndexBuffer::create(descriptor); + NOX_ENSURE_RETURN_NULLPTR_MSG(buffer != nullptr, "Couldn't create index buffer"); return buffer; } diff --git a/src/opengl/gl_swapchain.cpp b/src/opengl/gl_swapchain.cpp index 8320fb40..75ad80d1 100644 --- a/src/opengl/gl_swapchain.cpp +++ b/src/opengl/gl_swapchain.cpp @@ -1,7 +1,9 @@ #include "asserts.h" #include "opengl/gl_context.h" +#include "opengl/gl_program.h" #include "opengl/gl_shader.h" #include "opengl/gl_swapchain.h" +#include "opengl/gl_texture.h" #include "opengl/gl_vertex_array.h" #include @@ -10,16 +12,7 @@ namespace nox { namespace { -ImageFormat queryDefaultFramebufferImageFormat() { - constexpr GLuint defaultFramebufferHandle = 0u; - - GLint alphaBits = 0; - glGetNamedFramebufferAttachmentParameteriv(defaultFramebufferHandle, GL_BACK_LEFT, GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE, &alphaBits); - - return ((alphaBits != 0) ? ImageFormat::RGBA8_UNORM : ImageFormat::RGB8_UNORM); -} - -constexpr auto presentVertexShaderSource = R"( +constexpr auto vertexShaderSource = R"( #version 460 core out gl_PerVertex { @@ -47,7 +40,7 @@ constexpr auto presentVertexShaderSource = R"( } )"; -constexpr auto presentFragmentShaderSource = R"( +constexpr auto fragmentShaderSource = R"( #version 460 core layout(binding = 0) uniform sampler2D fullscreenTexture; @@ -60,64 +53,93 @@ constexpr auto presentFragmentShaderSource = R"( } )"; +ImageFormat queryDefaultFramebufferImageFormat() { + constexpr GLuint defaultFramebufferHandle = 0u; + + GLint alphaBits = 0; + glGetNamedFramebufferAttachmentParameteriv(defaultFramebufferHandle, GL_BACK_LEFT, GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE, &alphaBits); + + return ((alphaBits != 0) ? ImageFormat::RGBA8_UNORM : ImageFormat::RGB8_UNORM); +} + +std::unique_ptr createPresentationProgram() { + const auto vertexShader = GLShader::create({ShaderType::VERTEX}); + NOX_ENSURE_RETURN_NULLPTR(vertexShader != nullptr); + NOX_ENSURE_RETURN_NULLPTR(vertexShader->compile(vertexShaderSource)); + + const auto fragmentShader = GLShader::create({ShaderType::FRAGMENT}); + NOX_ENSURE_RETURN_NULLPTR(fragmentShader != nullptr); + NOX_ENSURE_RETURN_NULLPTR(fragmentShader->compile(fragmentShaderSource)); + + auto program = std::make_unique(); + program->attachShader(vertexShader->getHandle()); + program->attachShader(fragmentShader->getHandle()); + NOX_ENSURE_RETURN_NULLPTR(program->link()); + + return program; +} + } // namespace -std::unique_ptr GLSwapchain::create(const SwapchainDescriptor &descriptor, std::unique_ptr context) { +std::unique_ptr GLSwapchain::create(const SwapchainDescriptor &descriptor, + std::unique_ptr context, + GLVertexArrayRegistry ®istry) { const auto *presentMode = std::get_if(&descriptor.presentMode); NOX_ENSURE_RETURN_NULLPTR(presentMode != nullptr); context->setSwapInterval(presentMode->vSync); - auto swapchain = std::make_unique(std::move(context), descriptor.size); - NOX_ENSURE_RETURN_NULLPTR(swapchain->initializePresentationProgram()); + auto format = queryDefaultFramebufferImageFormat(); + auto texture = std::make_unique(Texture2DDescriptor{format, descriptor.size}); + + auto program = createPresentationProgram(); + NOX_ENSURE_RETURN_NULLPTR(program != nullptr); + + auto swapchain = std::make_unique(std::move(context), + std::move(program), + std::move(texture), + registry); return swapchain; } -GLSwapchain::GLSwapchain(std::unique_ptr context, Vector2D size) +GLSwapchain::GLSwapchain(std::unique_ptr context, + std::unique_ptr program, + std::unique_ptr texture, + GLVertexArrayRegistry ®istry) : m_context{std::move(context)}, - m_presentationTexture{{{queryDefaultFramebufferImageFormat()}, size}}, - m_size{size} {} - -std::vector GLSwapchain::getSwapchainTextures() const { - return {1u, &m_presentationTexture}; + m_presentationProgram{std::move(program)}, + m_presentationTexture{std::move(texture)}, + m_rVertexArrayRegistry{registry} { + m_rVertexArrayRegistry.registerVertexArray({}); } -void GLSwapchain::present() const { - const auto &vertexArrayRegistry = GLVertexArrayRegistry::instance(); - const auto &emptyVertexArray = vertexArrayRegistry.getVertexArray(0u); - - emptyVertexArray.bind(); - m_presentationTexture.bind(0u); - - m_presentationProgram.bind(); - glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); - m_presentationProgram.unbind(); +GLSwapchain::~GLSwapchain() { + m_rVertexArrayRegistry.unregisterVertexArray({}); +} - m_context->swapBuffers(); +Vector2D GLSwapchain::getSize() const { + auto size = m_presentationTexture->getSize(); + return {size.x(), size.y()}; } ImageFormat GLSwapchain::getSurfaceFormat() const { - return m_presentationTexture.getFormat(); + return m_presentationTexture->getFormat(); } -Vector2D GLSwapchain::getSize() const { - return m_size; +std::vector GLSwapchain::getSwapchainTextures() const { + return {1u, m_presentationTexture.get()}; } -bool GLSwapchain::initializePresentationProgram() { - const auto presentVertexShader = GLShader::create({ShaderType::VERTEX}); - NOX_ENSURE_RETURN_FALSE(presentVertexShader != nullptr); - NOX_ENSURE_RETURN_FALSE(presentVertexShader->compile(presentVertexShaderSource)); - - const auto presentFragmentShader = GLShader::create({ShaderType::FRAGMENT}); - NOX_ENSURE_RETURN_FALSE(presentFragmentShader != nullptr); - NOX_ENSURE_RETURN_FALSE(presentFragmentShader->compile(presentFragmentShaderSource)); +void GLSwapchain::present() const { + auto &vertexArray = m_rVertexArrayRegistry.getVertexArray({}); + vertexArray.bind(); + m_presentationTexture->bind(0u); - m_presentationProgram.attachShader(presentVertexShader->getHandle()); - m_presentationProgram.attachShader(presentFragmentShader->getHandle()); - NOX_ENSURE_RETURN_FALSE(m_presentationProgram.link()); + m_presentationProgram->bind(); + glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); + m_presentationProgram->unbind(); - return true; + m_context->swapBuffers(); } } // namespace nox diff --git a/src/opengl/gl_swapchain.h b/src/opengl/gl_swapchain.h index 3e7fb2ac..d83ef4f9 100644 --- a/src/opengl/gl_swapchain.h +++ b/src/opengl/gl_swapchain.h @@ -1,19 +1,25 @@ #pragma once -#include "opengl/gl_program.h" -#include "opengl/gl_texture.h" - #include namespace nox { class GLContext; +class GLProgram; +class GLTexture2D; +class GLVertexArrayRegistry; class GLSwapchain final : public Swapchain { public: - [[nodiscard]] static std::unique_ptr create(const SwapchainDescriptor &descriptor, std::unique_ptr context); + [[nodiscard]] static std::unique_ptr create(const SwapchainDescriptor &descriptor, + std::unique_ptr context, + GLVertexArrayRegistry ®istr); - GLSwapchain(std::unique_ptr context, Vector2D size); + GLSwapchain(std::unique_ptr context, + std::unique_ptr program, + std::unique_ptr texture, + GLVertexArrayRegistry ®istry); + ~GLSwapchain() override; Vector2D getSize() const override; ImageFormat getSurfaceFormat() const override; @@ -21,14 +27,11 @@ class GLSwapchain final : public Swapchain { void present() const override; - private: - [[nodiscard]] bool initializePresentationProgram(); - private: std::unique_ptr m_context{nullptr}; - GLProgram m_presentationProgram{}; - GLTexture2D m_presentationTexture; - Vector2D m_size; + std::unique_ptr m_presentationProgram{nullptr}; + std::unique_ptr m_presentationTexture{nullptr}; + GLVertexArrayRegistry &m_rVertexArrayRegistry; }; } // namespace nox diff --git a/src/opengl/gl_texture.cpp b/src/opengl/gl_texture.cpp index 6343ffcd..96db1631 100644 --- a/src/opengl/gl_texture.cpp +++ b/src/opengl/gl_texture.cpp @@ -240,7 +240,8 @@ bool GLTexture2D::validateInput(const Texture2DDescriptor &descriptor) { } GLTexture2D::GLTexture2D(const Texture2DDescriptor &descriptor) - : GLTexture{descriptor, TextureType::TEXTURE2D} { + : GLTexture{descriptor, TextureType::TEXTURE2D}, + m_size{descriptor.size} { auto width = static_cast(descriptor.size.x()); auto height = static_cast(descriptor.size.y()); auto format = mapTextureFormat(descriptor.format); @@ -262,4 +263,8 @@ void GLTexture2D::write(const TextureWriteDescriptor &descriptor) { descriptor.data); } +Vector3D GLTexture2D::getSize() const { + return Vector3D(m_size.x(), m_size.y(), 0u); +} + } // namespace nox diff --git a/src/opengl/gl_texture.h b/src/opengl/gl_texture.h index ce880a12..7ae4f2e3 100644 --- a/src/opengl/gl_texture.h +++ b/src/opengl/gl_texture.h @@ -20,6 +20,7 @@ class GLTexture : public Texture { protected: TextureType m_type{TextureType::NONE}; ImageFormat m_format{ImageFormat::NONE}; + Vector3D m_size{}; uint32_t m_handle{0u}; }; @@ -27,9 +28,14 @@ class GLTexture2D final : public GLTexture { public: [[nodiscard]] static bool validateInput(const Texture2DDescriptor &descriptor); - GLTexture2D(const Texture2DDescriptor &descriptor); + explicit GLTexture2D(const Texture2DDescriptor &descriptor); void write(const TextureWriteDescriptor &descriptor) override; + + Vector3D getSize() const override; + + private: + Vector2D m_size{}; }; } // namespace nox diff --git a/src/opengl/gl_vertex_array.cpp b/src/opengl/gl_vertex_array.cpp index edddffba..988ef8c1 100644 --- a/src/opengl/gl_vertex_array.cpp +++ b/src/opengl/gl_vertex_array.cpp @@ -27,12 +27,11 @@ GLenum mapVertexAttributeTypeToEnum(VertexAttributeType type) { } // namespace -GLVertexArray::GLVertexArray(VertexAttributes vertexAttributes) - : m_vertexAttributes{std::move(vertexAttributes)} { +GLVertexArray::GLVertexArray(const VertexAttributes &vertexAttributes) { glCreateVertexArrays(1, &m_handle); - for (size_t i = 0u; i < m_vertexAttributes.size(); i++) { - const auto &vertexAttribute = m_vertexAttributes[i]; + for (size_t i = 0u; i < vertexAttributes.size(); i++) { + const auto &vertexAttribute = vertexAttributes[i]; auto descriptor = getVertexAttributeFormatDescriptor(vertexAttribute); auto index = static_cast(i); auto componentsCount = static_cast(descriptor.componentsCount); @@ -48,6 +47,10 @@ GLVertexArray::GLVertexArray(VertexAttributes vertexAttributes) } } +GLVertexArray::~GLVertexArray() { + glDeleteVertexArrays(1, &m_handle); +} + void GLVertexArray::setVertexBuffer(uint32_t vertexBufferHandle) { constexpr GLintptr offsetToFirstElementInsideBuffer = 0; glVertexArrayVertexBuffer(m_handle, @@ -71,81 +74,51 @@ GLVertexArrayRegistry &GLVertexArrayRegistry::instance() { return registry; } -GLVertexArrayRegistry::GLVertexArrayRegistry() { - m_vertexArrays.emplace_back(GLVertexArray({}), 0u); -} - -GLVertexArrayRegistry::~GLVertexArrayRegistry() { - NOX_ASSERT(m_vertexArrays.size() == 1u); - - erase(0u); -} - -uint32_t GLVertexArrayRegistry::registerVertexArray(const VertexAttributes &vertexAttributes) { +void GLVertexArrayRegistry::registerVertexArray(const VertexAttributes &vertexAttributes) { if (!contains(vertexAttributes)) { - m_vertexArrays.emplace_back(vertexAttributes, 0u); + m_vertexArrays.emplace(vertexAttributes, std::make_unique(vertexAttributes)); } - - auto index = find(vertexAttributes); - auto &[vertexArray, references] = m_vertexArrays[index]; - references++; - - return index; } -void GLVertexArrayRegistry::unregisterVertexArray(uint32_t index) { - NOX_ASSERT(index < static_cast(m_vertexArrays.size())); +void GLVertexArrayRegistry::unregisterVertexArray(const VertexAttributes &vertexAttributes) { + NOX_ASSERT(contains(vertexAttributes)); - auto &[vertexArray, references] = m_vertexArrays[index]; - references--; - if (references == 0u) { - erase(index); - } + m_vertexArrays.erase(vertexAttributes); } -void GLVertexArrayRegistry::setBoundVertexArrayIndex(uint32_t index) { - m_boundVertexArrayIndex = index; -} +void GLVertexArrayRegistry::setBoundVertexArray(const VertexAttributes &vertexAttributes) { + NOX_ASSERT(contains(vertexAttributes)); -uint32_t GLVertexArrayRegistry::getBoundVertexArrayIndex() const { - return m_boundVertexArrayIndex; + m_boundVertexArray = m_vertexArrays.at(vertexAttributes).get(); } -GLVertexArray &GLVertexArrayRegistry::getVertexArray(uint32_t index) { - NOX_ASSERT(index < static_cast(m_vertexArrays.size())); +GLVertexArray &GLVertexArrayRegistry::getBoundVertexArray() { + NOX_ASSERT(m_boundVertexArray != nullptr); - auto &[vertexArray, references] = m_vertexArrays[index]; - return vertexArray; + return *m_boundVertexArray; } -const GLVertexArray &GLVertexArrayRegistry::getVertexArray(uint32_t index) const { - NOX_ASSERT(index < static_cast(m_vertexArrays.size())); +const GLVertexArray &GLVertexArrayRegistry::getBoundVertexArray() const { + NOX_ASSERT(m_boundVertexArray != nullptr); - const auto &[vertexArray, references] = m_vertexArrays[index]; - return vertexArray; + return *m_boundVertexArray; } -bool GLVertexArrayRegistry::contains(const VertexAttributes &vertexAttributes) const { - return (find(vertexAttributes) < static_cast(m_vertexArrays.size())); +GLVertexArray &GLVertexArrayRegistry::getVertexArray(const VertexAttributes &vertexAttributes) { + NOX_ASSERT(contains(vertexAttributes)); + + return *m_vertexArrays.at(vertexAttributes); } -uint32_t GLVertexArrayRegistry::find(const VertexAttributes &vertexAttributes) const { - for (size_t i = 0u; i < m_vertexArrays.size(); i++) { - const auto &[vertexArray, references] = m_vertexArrays[i]; - if (vertexArray.getVertexAttributes() == vertexAttributes) { - return (static_cast(i)); - } - } +const GLVertexArray &GLVertexArrayRegistry::getVertexArray(const VertexAttributes &vertexAttributes) const { + NOX_ASSERT(contains(vertexAttributes)); - return (static_cast(m_vertexArrays.size())); + return *m_vertexArrays.at(vertexAttributes); } -void GLVertexArrayRegistry::erase(uint32_t index) { - const auto &[vertexArray, references] = m_vertexArrays[index]; - m_vertexArrays.erase(m_vertexArrays.begin() + index); - - auto handle = vertexArray.getHandle(); - glDeleteVertexArrays(1, &handle); +bool GLVertexArrayRegistry::contains(const VertexAttributes &vertexAttributes) const { + auto it = m_vertexArrays.find(vertexAttributes); + return (it != m_vertexArrays.end()); } } // namespace nox diff --git a/src/opengl/gl_vertex_array.h b/src/opengl/gl_vertex_array.h index 71fae442..74f83b7c 100644 --- a/src/opengl/gl_vertex_array.h +++ b/src/opengl/gl_vertex_array.h @@ -2,18 +2,15 @@ #include +#include #include -#include namespace nox { class GLVertexArray final { public: - explicit GLVertexArray(VertexAttributes vertexAttributes); - - [[nodiscard]] const VertexAttributes &getVertexAttributes() const { - return m_vertexAttributes; - } + explicit GLVertexArray(const VertexAttributes &vertexAttributes); + ~GLVertexArray(); [[nodiscard]] uint32_t getHandle() const { return m_handle; @@ -25,7 +22,6 @@ class GLVertexArray final { void bind() const; private: - VertexAttributes m_vertexAttributes; uint32_t m_currentBindingIndex{0u}; uint32_t m_stride{0u}; uint32_t m_handle{0u}; @@ -35,32 +31,29 @@ class GLVertexArrayRegistry final { public: [[nodiscard]] static GLVertexArrayRegistry &instance(); - [[nodiscard]] uint32_t registerVertexArray(const VertexAttributes &vertexAttributes); - void unregisterVertexArray(uint32_t index); + void registerVertexArray(const VertexAttributes &vertexAttributes); + void unregisterVertexArray(const VertexAttributes &vertexAttributes); - void setBoundVertexArrayIndex(uint32_t index); - [[nodiscard]] uint32_t getBoundVertexArrayIndex() const; + void setBoundVertexArray(const VertexAttributes &vertexAttributes); + [[nodiscard]] GLVertexArray &getBoundVertexArray(); + [[nodiscard]] const GLVertexArray &getBoundVertexArray() const; - [[nodiscard]] GLVertexArray &getVertexArray(uint32_t index); - [[nodiscard]] const GLVertexArray &getVertexArray(uint32_t index) const; + [[nodiscard]] GLVertexArray &getVertexArray(const VertexAttributes &vertexAttributes); + [[nodiscard]] const GLVertexArray &getVertexArray(const VertexAttributes &vertexAttributes) const; private: [[nodiscard]] bool contains(const VertexAttributes &vertexAttributes) const; - [[nodiscard]] uint32_t find(const VertexAttributes &vertexAttributes) const; - void erase(uint32_t index); public: - GLVertexArrayRegistry(); + GLVertexArrayRegistry() = default; GLVertexArrayRegistry(const GLVertexArrayRegistry &) = delete; GLVertexArrayRegistry &operator=(const GLVertexArrayRegistry &) = delete; GLVertexArrayRegistry(GLVertexArrayRegistry &&) = delete; GLVertexArrayRegistry &operator=(GLVertexArrayRegistry &&) = delete; - ~GLVertexArrayRegistry(); private: - using VertexArray = std::pair; - std::vector m_vertexArrays; - uint32_t m_boundVertexArrayIndex{0u}; + std::map> m_vertexArrays; + GLVertexArray *m_boundVertexArray{nullptr}; }; } // namespace nox diff --git a/tests/unit_tests/opengl/CMakeLists.txt b/tests/unit_tests/opengl/CMakeLists.txt index f40fa89e..e4256009 100644 --- a/tests/unit_tests/opengl/CMakeLists.txt +++ b/tests/unit_tests/opengl/CMakeLists.txt @@ -87,6 +87,7 @@ endif() # -------------------------------------------------- set(NOX_UNIT_TESTS_OPENGL_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/CMakeLists.txt + ${CMAKE_CURRENT_SOURCE_DIR}/gl_buffer_tests.cpp ${CMAKE_CURRENT_SOURCE_DIR}/gl_context_tests.cpp ${CMAKE_CURRENT_SOURCE_DIR}/gl_program_tests.cpp ${CMAKE_CURRENT_SOURCE_DIR}/gl_shader_tests.cpp diff --git a/tests/unit_tests/opengl/gl_buffer_tests.cpp b/tests/unit_tests/opengl/gl_buffer_tests.cpp new file mode 100644 index 00000000..4640ac43 --- /dev/null +++ b/tests/unit_tests/opengl/gl_buffer_tests.cpp @@ -0,0 +1,8 @@ +#include "src/opengl/gl_buffer.h" + +#include "tests/base/opengl/gl_test_environment.h" + +#include +#include + +using namespace nox;