diff --git a/sources/Renderer/OpenGL/Buffer/GL2XVertexArray.cpp b/sources/Renderer/OpenGL/Buffer/GL2XVertexArray.cpp deleted file mode 100644 index 3e9db159c7..0000000000 --- a/sources/Renderer/OpenGL/Buffer/GL2XVertexArray.cpp +++ /dev/null @@ -1,128 +0,0 @@ -/* - * GL2XVertexArray.cpp - * - * Copyright (c) 2015 Lukas Hermanns. All rights reserved. - * Licensed under the terms of the BSD 3-Clause license (see LICENSE.txt). - */ - -#include "GL2XVertexArray.h" -#include "../Ext/GLExtensions.h" -#include "../RenderState/GLStateManager.h" -#include "../GLTypes.h" -#include "../GLCore.h" -#include "../../../Core/Exception.h" - - -namespace LLGL -{ - - -void GL2XVertexArray::BuildVertexLayout(GLuint bufferID, const ArrayView& attributes) -{ - attribs_.clear(); - attribs_.reserve(attributes.size()); - - for (const VertexAttribute& attrib : attributes) - BuildVertexAttribute(bufferID, attrib); - - Finalize(); -} - -void GL2XVertexArray::Bind(GLStateManager& stateMngr) const -{ - /* Enable required vertex arrays */ - for (const GL2XVertexAttrib& attr : attribs_) - { - stateMngr.BindBuffer(GLBufferTarget::ArrayBuffer, attr.buffer); - glVertexAttribPointer(attr.index, attr.size, attr.type, attr.normalized, attr.stride, attr.pointer); - glEnableVertexAttribArray(attr.index); - } - - //TODO: add case for disabling attrib arrays inbetween, e.g. when only index 0 and 2 is used (rare case probably) - /* Disable remaining vertex arrays */ - stateMngr.DisableVertexAttribArrays(attribIndexEnd_); -} - - -/* - * ======= Private: ======= - */ - -void GL2XVertexArray::BuildVertexAttribute(GLuint bufferID, const VertexAttribute& attribute) -{ - /* Check if instance divisor is used */ - if (attribute.instanceDivisor > 0) - LLGL_TRAP_FEATURE_NOT_SUPPORTED("per-instance vertex attributes"); - - /* Check if integral vertex attribute is used */ - bool isNormalizedFormat = IsNormalizedFormat(attribute.format); - bool isFloatFormat = IsFloatFormat(attribute.format); - - if (!isNormalizedFormat && !isFloatFormat) - LLGL_TRAP_FEATURE_NOT_SUPPORTED("integral vertex attributes"); - - /* Get data type and components of vector type */ - const FormatAttributes& formatAttribs = GetFormatAttribs(attribute.format); - if ((formatAttribs.flags & FormatFlags::SupportsVertex) == 0) - LLGL_TRAP_FEATURE_NOT_SUPPORTED("specified vertex attribute"); - - /* Convert offset to pointer sized type (for 32- and 64 bit builds) */ - GLenum dataType = GLTypes::Map(formatAttribs.dataType); - GLint components = static_cast(formatAttribs.components); - GLuint attribIndex = static_cast(attribute.location); - GLsizei stride = static_cast(attribute.stride); - GLsizeiptr offsetPtrSized = static_cast(attribute.offset); - - attribs_.push_back( - { - bufferID, - attribIndex, - components, - dataType, - GLBoolean(isNormalizedFormat), - stride, - reinterpret_cast(offsetPtrSized) - } - ); -} - -void GL2XVertexArray::Finalize() -{ - if (attribs_.empty()) - return; - - /* Validate attribute indices are unique and fill the entire range [0, N) */ - std::vector locationsTaken; - locationsTaken.resize(attribs_.size(), false); - - for (const auto& attr : attribs_) - { - if (attr.index > locationsTaken.size() || locationsTaken[attr.index]) - throw std::runtime_error("vertex attribute locations must fill the entire half-open range [0, N) for OpenGL 2.X"); - locationsTaken[attr.index] = true; - } - - /* Store upper bound for attribute indices */ - attribIndexEnd_ = attribs_.back().index + 1; - - /* Sort attributes by buffer binding and index in ascending order */ - std::sort( - attribs_.begin(), - attribs_.end(), - [](const GL2XVertexAttrib& lhs, const GL2XVertexAttrib& rhs) - { - if (lhs.buffer < rhs.buffer) - return true; - if (lhs.buffer > rhs.buffer) - return false; - return (lhs.index < rhs.index); - } - ); -} - - -} // /namespace LLGL - - - -// ================================================================================ diff --git a/sources/Renderer/OpenGL/Buffer/GL2XVertexArray.h b/sources/Renderer/OpenGL/Buffer/GL2XVertexArray.h deleted file mode 100644 index 9590a94ca9..0000000000 --- a/sources/Renderer/OpenGL/Buffer/GL2XVertexArray.h +++ /dev/null @@ -1,69 +0,0 @@ -/* - * GL2XVertexArray.h - * - * Copyright (c) 2015 Lukas Hermanns. All rights reserved. - * Licensed under the terms of the BSD 3-Clause license (see LICENSE.txt). - */ - -#ifndef LLGL_GL2X_VERTEX_ARRAY_H -#define LLGL_GL2X_VERTEX_ARRAY_H - - -#include -#include -#include "../OpenGL.h" -#include - - -namespace LLGL -{ - - -class GLStateManager; - -// This class emulates the Vertex-Array-Object (VAO) functionality, for GL 2.x. -class GL2XVertexArray -{ - - public: - - // Stores the vertex attributes for later use via glVertexAttrib*Pointer() functions. - void BuildVertexLayout(GLuint bufferID, const ArrayView& attributes); - - // Binds this vertex array. - void Bind(GLStateManager& stateMngr) const; - - private: - - struct GL2XVertexAttrib - { - GLuint buffer; - GLuint index; - GLint size; - GLenum type; - GLboolean normalized; - GLsizei stride; - const GLvoid* pointer; - }; - - private: - - void BuildVertexAttribute(GLuint bufferID, const VertexAttribute& attribute); - void Finalize(); - - private: - - std::vector attribs_; - GLuint attribIndexEnd_ = 0; - -}; - - -} // /namespace LLGL - - -#endif - - - -// ================================================================================ diff --git a/sources/Renderer/OpenGL/Buffer/GLBufferArrayWithVAO.cpp b/sources/Renderer/OpenGL/Buffer/GLBufferArrayWithVAO.cpp index 9ff9359424..ac4032702c 100644 --- a/sources/Renderer/OpenGL/Buffer/GLBufferArrayWithVAO.cpp +++ b/sources/Renderer/OpenGL/Buffer/GLBufferArrayWithVAO.cpp @@ -7,7 +7,6 @@ #include "GLBufferArrayWithVAO.h" #include "GLBufferWithVAO.h" -#include "../GLObjectUtils.h" #include "../RenderState/GLStateManager.h" #include "../../CheckedCast.h" #include "../../../Core/CoreUtils.h" @@ -21,82 +20,28 @@ namespace LLGL GLBufferArrayWithVAO::GLBufferArrayWithVAO(std::uint32_t numBuffers, Buffer* const * bufferArray) : GLBufferArray { numBuffers, bufferArray } { - #ifdef LLGL_GL_ENABLE_OPENGL2X - if (!HasNativeVAO()) + /* Build vertex array and finalize afterwards as it references multiple buffers */ + while (GLBuffer* bufferGL = NextArrayResource(numBuffers, bufferArray)) { - /* Build vertex array with emulator (for GL 2.x compatibility) */ - BuildVertexArrayWithEmulator(numBuffers, bufferArray); - } - else - #endif // /LLGL_GL_ENABLE_OPENGL2X - { - /* Build vertex array with native VAO */ - BuildVertexArrayWithVAO(numBuffers, bufferArray); - } -} - -void GLBufferArrayWithVAO::SetDebugName(const char* name) -{ - #ifdef LLGL_GL_ENABLE_OPENGL2X - if (HasNativeVAO()) - #endif - { - /* Set label for VAO */ - GLSetObjectLabel(GL_VERTEX_ARRAY, vao_.GetID(), name); - } -} - - -/* - * ======= Private: ======= - */ - -[[noreturn]] -static void ThrowNoVertexBufferErr() -{ - throw std::invalid_argument( - "cannot build vertex array with buffer that was not created with the 'LLGL::BindFlags::VertexBuffer' flag" - ); -} - -void GLBufferArrayWithVAO::BuildVertexArrayWithVAO(std::uint32_t numBuffers, Buffer* const * bufferArray) -{ - /* Bind VAO */ - GLStateManager::Get().BindVertexArray(GetVaoID()); - { - while (GLBuffer* bufferGL = NextArrayResource(numBuffers, bufferArray)) + if ((bufferGL->GetBindFlags() & BindFlags::VertexBuffer) != 0) { - if ((bufferGL->GetBindFlags() & BindFlags::VertexBuffer) != 0) - { - /* Bind VBO and build vertex layout */ - auto* vertexBufferGL = LLGL_CAST(GLBufferWithVAO*, bufferGL); - GLStateManager::Get().BindBuffer(GLBufferTarget::ArrayBuffer, vertexBufferGL->GetID()); - vao_.BuildVertexLayout(vertexBufferGL->GetVertexAttribs()); - } - else - ThrowNoVertexBufferErr(); + /* Bind VBO and build vertex layout */ + auto* vertexBufferGL = LLGL_CAST(GLBufferWithVAO*, bufferGL); + GLStateManager::Get().BindBuffer(GLBufferTarget::ArrayBuffer, vertexBufferGL->GetID()); + vertexArray_.BuildVertexLayout(vertexBufferGL->GetID(), vertexBufferGL->GetVertexAttribs()); } - } - GLStateManager::Get().BindVertexArray(0); -} - -#ifdef LLGL_GL_ENABLE_OPENGL2X - -void GLBufferArrayWithVAO::BuildVertexArrayWithEmulator(std::uint32_t numBuffers, Buffer* const * bufferArray) -{ - while (numBuffers-- > 0) - { - if (((*bufferArray)->GetBindFlags() & BindFlags::VertexBuffer) != 0) + else { - auto* vertexBufferGL = LLGL_CAST(GLBufferWithVAO*, (*bufferArray++)); - vertexArrayGL2X_.BuildVertexLayout(vertexBufferGL->GetID(), vertexBufferGL->GetVertexAttribs()); + LLGL_TRAP("cannot build vertex array with buffer that was not created with the 'LLGL::BindFlags::VertexBuffer' flag"); } - else - ThrowNoVertexBufferErr(); } + vertexArray_.Finalize(); } -#endif // /LLGL_GL_ENABLE_OPENGL2X +void GLBufferArrayWithVAO::SetDebugName(const char* name) +{ + vertexArray_.SetDebugName(name); +} } // /namespace LLGL diff --git a/sources/Renderer/OpenGL/Buffer/GLBufferArrayWithVAO.h b/sources/Renderer/OpenGL/Buffer/GLBufferArrayWithVAO.h index 84b214574e..bf7ecb0d83 100644 --- a/sources/Renderer/OpenGL/Buffer/GLBufferArrayWithVAO.h +++ b/sources/Renderer/OpenGL/Buffer/GLBufferArrayWithVAO.h @@ -10,10 +10,7 @@ #include "GLBufferArray.h" -#include "GLVertexArrayObject.h" -#ifdef LLGL_GL_ENABLE_OPENGL2X -# include "GL2XVertexArray.h" -#endif +#include "GLSharedContextVertexArray.h" namespace LLGL @@ -31,34 +28,15 @@ class GLBufferArrayWithVAO final : public GLBufferArray GLBufferArrayWithVAO(std::uint32_t numBuffers, Buffer* const * bufferArray); - // Returns the ID of the vertex-array-object (VAO) - inline GLuint GetVaoID() const - { - return vao_.GetID(); - } - - #ifdef LLGL_GL_ENABLE_OPENGL2X - // Returns the GL 2.x compatible vertex-array emulator. - inline const GL2XVertexArray& GetVertexArrayGL2X() const + // Returns the vertex array which can be shared across multiple GL contexts. + inline GLSharedContextVertexArray* GetVertexArray() { - return vertexArrayGL2X_; + return &vertexArray_; } - #endif private: - void BuildVertexArrayWithVAO(std::uint32_t numBuffers, Buffer* const * bufferArray); - #ifdef LLGL_GL_ENABLE_OPENGL2X - void BuildVertexArrayWithEmulator(std::uint32_t numBuffers, Buffer* const * bufferArray); - #endif - - private: - - GLVertexArrayObject vao_; - - #ifdef LLGL_GL_ENABLE_OPENGL2X - GL2XVertexArray vertexArrayGL2X_; - #endif + GLSharedContextVertexArray vertexArray_; }; diff --git a/sources/Renderer/OpenGL/Buffer/GLBufferWithVAO.cpp b/sources/Renderer/OpenGL/Buffer/GLBufferWithVAO.cpp index 9e8097fc4e..6a9880db5b 100644 --- a/sources/Renderer/OpenGL/Buffer/GLBufferWithVAO.cpp +++ b/sources/Renderer/OpenGL/Buffer/GLBufferWithVAO.cpp @@ -17,55 +17,26 @@ namespace LLGL GLBufferWithVAO::GLBufferWithVAO(long bindFlags, const char* debugName) : GLBuffer { bindFlags, debugName } { + if (debugName != nullptr) + { + const std::string vaoLabel = debugName + std::string(".VAO"); + vertexArray_.SetDebugName(vaoLabel.c_str()); + } } -void GLBufferWithVAO::BuildVertexArray(std::size_t numVertexAttribs, const VertexAttribute* vertexAttribs) +void GLBufferWithVAO::BuildVertexArray(const ArrayView& vertexAttribs) { /* Store vertex format (required if this buffer is used in a buffer array) */ - if (numVertexAttribs > 0) - vertexAttribs_ = std::vector(vertexAttribs, vertexAttribs + numVertexAttribs); - else + if (vertexAttribs.empty()) vertexAttribs_.clear(); - - #ifdef LLGL_GL_ENABLE_OPENGL2X - if (!HasNativeVAO()) - { - /* Build vertex array with emulator (for GL 2.x compatibility) */ - BuildVertexArrayWithEmulator(); - } else - #endif // /LLGL_GL_ENABLE_OPENGL2X - { - /* Build vertex array with native VAO */ - BuildVertexArrayWithVAO(); - } -} + vertexAttribs_ = std::vector(vertexAttribs.begin(), vertexAttribs.end()); - -/* - * ======= Private: ======= - */ - -void GLBufferWithVAO::BuildVertexArrayWithVAO() -{ - /* Bind VAO and build vertex layout */ - GLStateManager::Get().BindVertexArray(GetVaoID()); - { - GLStateManager::Get().BindBuffer(GLBufferTarget::ArrayBuffer, GetID()); - vao_.BuildVertexLayout(vertexAttribs_); - } - GLStateManager::Get().BindVertexArray(0); + /* Build vertex layout and finalize immediately as it only references a single buffer */ + vertexArray_.BuildVertexLayout(GetID(), vertexAttribs_); + vertexArray_.Finalize(); } -#ifdef LLGL_GL_ENABLE_OPENGL2X - -void GLBufferWithVAO::BuildVertexArrayWithEmulator() -{ - vertexArrayGL2X_.BuildVertexLayout(GetID(), vertexAttribs_); -} - -#endif // /LLGL_GL_ENABLE_OPENGL2X - } // /namespace LLGL diff --git a/sources/Renderer/OpenGL/Buffer/GLBufferWithVAO.h b/sources/Renderer/OpenGL/Buffer/GLBufferWithVAO.h index 24645437ce..4d5cc9f96c 100644 --- a/sources/Renderer/OpenGL/Buffer/GLBufferWithVAO.h +++ b/sources/Renderer/OpenGL/Buffer/GLBufferWithVAO.h @@ -11,9 +11,8 @@ #include "GLBuffer.h" #include "GLVertexArrayObject.h" -#ifdef LLGL_GL_ENABLE_OPENGL2X -# include "GL2XVertexArray.h" -#endif +#include "GLSharedContextVertexArray.h" +#include namespace LLGL @@ -27,13 +26,7 @@ class GLBufferWithVAO final : public GLBuffer GLBufferWithVAO(long bindFlags, const char* debugName = nullptr); - void BuildVertexArray(std::size_t numVertexAttribs, const VertexAttribute* vertexAttribs); - - // Returns the ID of the vertex-array-object (VAO) - inline GLuint GetVaoID() const - { - return vao_.GetID(); - } + void BuildVertexArray(const ArrayView& vertexAttribs); // Returns the list of vertex attributes. inline const std::vector& GetVertexAttribs() const @@ -41,29 +34,16 @@ class GLBufferWithVAO final : public GLBuffer return vertexAttribs_; } - #ifdef LLGL_GL_ENABLE_OPENGL2X - // Returns the GL 2.x compatible vertex-array emulator. - inline const GL2XVertexArray& GetVertexArrayGL2X() const + // Returns the vertex array which can be shared across multiple GL contexts. + inline GLSharedContextVertexArray* GetVertexArray() { - return vertexArrayGL2X_; + return &vertexArray_; } - #endif private: - void BuildVertexArrayWithVAO(); - #ifdef LLGL_GL_ENABLE_OPENGL2X - void BuildVertexArrayWithEmulator(); - #endif - - private: - - GLVertexArrayObject vao_; std::vector vertexAttribs_; - - #ifdef LLGL_GL_ENABLE_OPENGL2X - GL2XVertexArray vertexArrayGL2X_; - #endif + GLSharedContextVertexArray vertexArray_; }; diff --git a/sources/Renderer/OpenGL/Buffer/GLSharedContextVertexArray.cpp b/sources/Renderer/OpenGL/Buffer/GLSharedContextVertexArray.cpp new file mode 100644 index 0000000000..367fe4d6a8 --- /dev/null +++ b/sources/Renderer/OpenGL/Buffer/GLSharedContextVertexArray.cpp @@ -0,0 +1,239 @@ +/* + * GLSharedContextVertexArray.cpp + * + * Copyright (c) 2015 Lukas Hermanns. All rights reserved. + * Licensed under the terms of the BSD 3-Clause license (see LICENSE.txt). + */ + +#include "GLSharedContextVertexArray.h" +#include "../Ext/GLExtensions.h" +#include "../Ext/GLExtensionRegistry.h" +#include "../RenderState/GLStateManager.h" +#include "../GLTypes.h" +#include "../GLCore.h" +#include "../GLObjectUtils.h" +#include "../../../Core/Assertion.h" +#include "../Platform/GLContext.h" +#include + + +namespace LLGL +{ + + +void GLSharedContextVertexArray::BuildVertexLayout(GLuint bufferID, const ArrayView& attributes) +{ + #ifdef LLGL_GL_ENABLE_OPENGL2X + if (!HasNativeVAO()) + { + /* Bind vertex array for OpenGL 2.x */ + BuildVertexLayoutForGL2X(bufferID, attributes); + } + else + #endif + { + BuildVertexLayoutForGL3Plus(bufferID, attributes); + } +} + +void GLSharedContextVertexArray::Finalize() +{ + #ifdef LLGL_GL_ENABLE_OPENGL2X + if (!HasNativeVAO()) + { + /* Finalize vertex array for OpenGL 2.x */ + FinalizeForGL2X(); + } + #endif // /LLGL_GL_ENABLE_OPENGL2X +} + +void GLSharedContextVertexArray::Bind(GLStateManager& stateMngr) +{ + #ifdef LLGL_GL_ENABLE_OPENGL2X + if (!HasNativeVAO()) + { + /* Bind vertex array for OpenGL 2.x */ + BindForGL2X(stateMngr); + } + else + #endif + { + /* Bind vertex array for OpenGL 3+ using VAO */ + BindForGL3Plus(stateMngr); + } +} + +void GLSharedContextVertexArray::SetDebugName(const char* name) +{ + /* Store debug name */ + debugName_ = (name != nullptr ? name : ""); + + /* Invalidate debug name for all context dependent VAOs */ + for (GLContextVAO& contextVAO : contextDependentVAOs_) + contextVAO.isObjectLabelDirty = true; + + /* If this vertex array already has its attributes set, get the current VAO to cause invaldiated labels to be updated */ + if (!attribs_.empty()) + (void)GetVAOForCurrentContext(); +} + +void GLSharedContextVertexArray::GLContextVAO::SetObjectLabel(const char* label) +{ + #ifdef LLGL_GL_ENABLE_OPENGL2X + if (HasNativeVAO()) + #endif + { + /* Set label for VAO */ + GLSetObjectLabel(GL_VERTEX_ARRAY, vao.GetID(), label); + isObjectLabelDirty = false; + } +} + + +/* + * ======= Private: ======= + */ + +GLVertexArrayObject& GLSharedContextVertexArray::GetVAOForCurrentContext() +{ + /* Check if there's already an entry for the current context */ + const unsigned contextIndex = GLContext::GetCurrentGlobalIndex(); + LLGL_ASSERT(contextIndex > 0); + + const std::size_t vaoIndex = static_cast(contextIndex) - 1; + if (vaoIndex >= contextDependentVAOs_.size()) + { + /* Resize container and fill new entry */ + contextDependentVAOs_.resize(vaoIndex + 1); + contextDependentVAOs_[vaoIndex].vao.BuildVertexLayout(attribs_); + if (!debugName_.empty()) + contextDependentVAOs_[vaoIndex].SetObjectLabel(debugName_.c_str()); + } + else if (contextDependentVAOs_[vaoIndex].vao.GetID() == 0) + { + /* Fill empty entry in container */ + contextDependentVAOs_[vaoIndex].vao.BuildVertexLayout(attribs_); + if (!debugName_.empty()) + contextDependentVAOs_[vaoIndex].SetObjectLabel(debugName_.c_str()); + } + else if (contextDependentVAOs_[vaoIndex].isObjectLabelDirty) + { + /* Udpate debug label if it has been invalidated */ + if (!debugName_.empty()) + contextDependentVAOs_[vaoIndex].SetObjectLabel(debugName_.c_str()); + } + + /* Return VAO for current context */ + return contextDependentVAOs_[vaoIndex].vao; +} + +void GLSharedContextVertexArray::BuildVertexLayoutForGL3Plus(GLuint bufferID, const ArrayView& attributes) +{ + const std::size_t startOffset = attribs_.size(); + attribs_.resize(startOffset + attributes.size()); + + for_range(i, attributes.size()) + { + /* Convert to GLVertexAttribute */ + GLConvertVertexAttrib(attribs_[startOffset + i], attributes[i], bufferID); + } +} + +void GLSharedContextVertexArray::BindForGL3Plus(GLStateManager& stateMngr) +{ + stateMngr.BindVertexArray(GetVAOForCurrentContext().GetID()); +} + +#ifdef LLGL_GL_ENABLE_OPENGL2X + +void GLSharedContextVertexArray::BuildVertexLayoutForGL2X(GLuint bufferID, const ArrayView& attributes) +{ + const std::size_t startOffset = attribs_.size(); + attribs_.resize(startOffset + attributes.size()); + + for_range(i, attributes.size()) + { + const VertexAttribute& inAttrib = attributes[i]; + + /* Check if instance divisor is used */ + if (inAttrib.instanceDivisor > 0) + LLGL_TRAP_FEATURE_NOT_SUPPORTED("per-instance vertex attributes"); + + /* Check if integral vertex attribute is used */ + bool isNormalizedFormat = IsNormalizedFormat(inAttrib.format); + bool isFloatFormat = IsFloatFormat(inAttrib.format); + + if (!isNormalizedFormat && !isFloatFormat) + LLGL_TRAP_FEATURE_NOT_SUPPORTED("integral vertex attributes"); + + /* Get data type and components of vector type */ + const FormatAttributes& formatAttribs = GetFormatAttribs(inAttrib.format); + if ((formatAttribs.flags & FormatFlags::SupportsVertex) == 0) + LLGL_TRAP_FEATURE_NOT_SUPPORTED("specified vertex attribute"); + + /* Convert to GLVertexAttribute */ + GLConvertVertexAttrib(attribs_[startOffset + i], inAttrib, bufferID); + } + + FinalizeForGL2X(); +} + +void GLSharedContextVertexArray::BindForGL2X(GLStateManager& stateMngr) +{ + /* Enable required vertex arrays */ + for (const GLVertexAttribute& attr : attribs_) + { + stateMngr.BindBuffer(GLBufferTarget::ArrayBuffer, attr.buffer); + glVertexAttribPointer(attr.index, attr.size, attr.type, attr.normalized, attr.stride, reinterpret_cast(attr.offsetPtrSized)); + glEnableVertexAttribArray(attr.index); + } + + //TODO: add case for disabling attrib arrays inbetween, e.g. when only index 0 and 2 is used (rare case probably) + /* Disable remaining vertex arrays */ + stateMngr.DisableVertexAttribArrays(attribIndexEnd_); +} + +void GLSharedContextVertexArray::FinalizeForGL2X() +{ + if (attribs_.empty()) + return; + + /* Validate attribute indices are unique and fill the entire range [0, N) */ + std::vector locationsTaken; + locationsTaken.resize(attribs_.size(), false); + + for (const GLVertexAttribute& attr : attribs_) + { + LLGL_ASSERT( + !(attr.index > locationsTaken.size() || locationsTaken[attr.index]), + "vertex attribute locations must fill the entire half-open range [0, N) for OpenGL 2.X" + ); + locationsTaken[attr.index] = true; + } + + /* Store upper bound for attribute indices */ + attribIndexEnd_ = attribs_.back().index + 1; + + /* Sort attributes by buffer binding and index in ascending order */ + std::sort( + attribs_.begin(), + attribs_.end(), + [](const GLVertexAttribute& lhs, const GLVertexAttribute& rhs) + { + if (lhs.buffer < rhs.buffer) + return true; + if (lhs.buffer > rhs.buffer) + return false; + return (lhs.index < rhs.index); + } + ); +} + +#endif // /LLGL_GL_ENABLE_OPENGL2X + + +} // /namespace LLGL + + + +// ================================================================================ diff --git a/sources/Renderer/OpenGL/Buffer/GLSharedContextVertexArray.h b/sources/Renderer/OpenGL/Buffer/GLSharedContextVertexArray.h new file mode 100644 index 0000000000..e89ec2b4fc --- /dev/null +++ b/sources/Renderer/OpenGL/Buffer/GLSharedContextVertexArray.h @@ -0,0 +1,89 @@ +/* + * GLSharedContextVertexArray.h + * + * Copyright (c) 2015 Lukas Hermanns. All rights reserved. + * Licensed under the terms of the BSD 3-Clause license (see LICENSE.txt). + */ + +#ifndef LLGL_GL2X_VERTEX_ARRAY_H +#define LLGL_GL2X_VERTEX_ARRAY_H + + +#include +#include +#include "GLVertexArrayObject.h" +#include + + +namespace LLGL +{ + + +class GLStateManager; + +// This class emulates the Vertex-Array-Object (VAO) functionality, for GL 2.x. +class GLSharedContextVertexArray +{ + + public: + + // Stores the vertex attributes for later use via glVertexAttrib*Pointer() functions. + void BuildVertexLayout(GLuint bufferID, const ArrayView& attributes); + + // Finalize the vertex array. + void Finalize(); + + // Binds this vertex array. + void Bind(GLStateManager& stateMngr); + + // Sets the debug label for all VAOs. + void SetDebugName(const char* name); + + private: + + struct GLContextVAO + { + GLVertexArrayObject vao; + bool isObjectLabelDirty = false; + + void SetObjectLabel(const char* label); + }; + + private: + + // Returns the VAO for the current GL context and creates it on demand. + GLVertexArrayObject& GetVAOForCurrentContext(); + + void BuildVertexLayoutForGL3Plus(GLuint bufferID, const ArrayView& attributes); + void BindForGL3Plus(GLStateManager& stateMngr); + + #ifdef LLGL_GL_ENABLE_OPENGL2X + + void BuildVertexLayoutForGL2X(GLuint bufferID, const ArrayView& attributes); + void BindForGL2X(GLStateManager& stateMngr); + void FinalizeForGL2X(); + + #endif // /LLGL_GL_ENABLE_OPENGL2X + + private: + + std::vector attribs_; + std::vector contextDependentVAOs_; + + #ifdef LLGL_GL_ENABLE_OPENGL2X + GLuint attribIndexEnd_ = 0; + #endif + + std::string debugName_; + +}; + + +} // /namespace LLGL + + +#endif + + + +// ================================================================================ diff --git a/sources/Renderer/OpenGL/Buffer/GLVertexArrayObject.cpp b/sources/Renderer/OpenGL/Buffer/GLVertexArrayObject.cpp index 53e82f17b3..fd60e7808b 100644 --- a/sources/Renderer/OpenGL/Buffer/GLVertexArrayObject.cpp +++ b/sources/Renderer/OpenGL/Buffer/GLVertexArrayObject.cpp @@ -19,25 +19,56 @@ namespace LLGL { -GLVertexArrayObject::GLVertexArrayObject() +void GLConvertVertexAttrib(GLVertexAttribute& dst, const VertexAttribute& src, GLuint srcBuffer) { - if (HasNativeVAO()) - glGenVertexArrays(1, &id_); + /* Get data type and components of vector type */ + const FormatAttributes& formatAttribs = GetFormatAttribs(src.format); + if ((formatAttribs.flags & FormatFlags::SupportsVertex) == 0) + { + if (const char* formatStr = ToString(src.format)) + LLGL_TRAP("LLGL::Format::%s cannot be used for vertex attributes", formatStr); + else + LLGL_TRAP("unknown format cannot be used for vertex attributes"); + } + + /* Convert offset to pointer sized type (for 32- and 64 bit builds) */ + dst.buffer = srcBuffer; + dst.index = static_cast(src.location); + dst.size = static_cast(formatAttribs.components); + dst.type = GLTypes::Map(formatAttribs.dataType); + dst.normalized = GLBoolean((formatAttribs.flags & FormatFlags::IsNormalized) != 0); + dst.stride = static_cast(src.stride); + dst.offsetPtrSized = static_cast(src.offset); + dst.divisor = static_cast(src.instanceDivisor); + dst.isInteger = (formatAttribs.flags & FormatFlags::IsNormalized) == 0 && !IsFloatFormat(src.format); } -GLVertexArrayObject::~GLVertexArrayObject() +void GLVertexArrayObject::Release() { - if (HasNativeVAO()) + //TODO: this must use some form of deferred deletion as this d'tor is not guaranteed to be invoked with the correct GL context in place + if (id_ != 0) { glDeleteVertexArrays(1, &id_); GLStateManager::Get().NotifyVertexArrayRelease(id_); + id_ = 0; } } -void GLVertexArrayObject::BuildVertexLayout(const ArrayView& attributes) +void GLVertexArrayObject::BuildVertexLayout(const ArrayView& attributes) { - for (const VertexAttribute& attrib : attributes) - BuildVertexAttribute(attrib); + LLGL_ASSERT_GL_EXT(ARB_vertex_array_object); + + /* Generate a VAO if not already done */ + if (id_ == 0) + glGenVertexArrays(1, &id_); + + /* Build vertex attributes for this VAO */ + GLStateManager::Get().BindVertexArray(id_); + { + for (const GLVertexAttribute& attrib : attributes) + BuildVertexAttribute(attrib); + } + GLStateManager::Get().BindVertexArray(0); } @@ -45,56 +76,38 @@ void GLVertexArrayObject::BuildVertexLayout(const ArrayView& at * ======= Private: ======= */ -void GLVertexArrayObject::BuildVertexAttribute(const VertexAttribute& attribute) +void GLVertexArrayObject::BuildVertexAttribute(const GLVertexAttribute& attribute) { - LLGL_ASSERT_GL_EXT(ARB_vertex_array_object); - - /* Get data type and components of vector type */ - const FormatAttributes& formatAttribs = GetFormatAttribs(attribute.format); - if ((formatAttribs.flags & FormatFlags::SupportsVertex) == 0) - { - if (const char* formatStr = ToString(attribute.format)) - LLGL_TRAP("LLGL::Format::%s cannot be used for vertex attributes", formatStr); - else - LLGL_TRAP("unknown format cannot be used for vertex attributes"); - } - - /* Convert offset to pointer sized type (for 32- and 64 bit builds) */ - const GLenum dataType = GLTypes::Map(formatAttribs.dataType); - const GLint components = static_cast(formatAttribs.components); - const GLuint attribIndex = static_cast(attribute.location); - const GLsizei stride = static_cast(attribute.stride); - const GLsizeiptr offsetPtrSized = static_cast(attribute.offset); + GLStateManager::Get().BindBuffer(GLBufferTarget::ArrayBuffer, attribute.buffer); /* Enable array index in currently bound VAO */ - glEnableVertexAttribArray(attribIndex); + glEnableVertexAttribArray(attribute.index); /* Set instance divisor */ - if (attribute.instanceDivisor > 0) - glVertexAttribDivisor(attribIndex, attribute.instanceDivisor); + if (attribute.divisor > 0) + glVertexAttribDivisor(attribute.index, attribute.divisor); /* Use currently bound VBO for VertexAttribPointer functions */ - if ((formatAttribs.flags & FormatFlags::IsNormalized) == 0 && !IsFloatFormat(attribute.format)) + if (attribute.isInteger) { LLGL_ASSERT_GL_EXT(EXT_gpu_shader4, "integral vertex attributes"); glVertexAttribIPointer( - attribIndex, - components, - dataType, - stride, - reinterpret_cast(offsetPtrSized) + attribute.index, + attribute.size, + attribute.type, + attribute.stride, + reinterpret_cast(attribute.offsetPtrSized) ); } else { - const GLboolean normalized = GLBoolean((formatAttribs.flags & FormatFlags::IsNormalized) != 0); glVertexAttribPointer( - attribIndex, - components, - dataType, - normalized, - stride, - reinterpret_cast(offsetPtrSized) + attribute.index, + attribute.size, + attribute.type, + attribute.normalized, + attribute.stride, + reinterpret_cast(attribute.offsetPtrSized) ); } } diff --git a/sources/Renderer/OpenGL/Buffer/GLVertexArrayObject.h b/sources/Renderer/OpenGL/Buffer/GLVertexArrayObject.h index 40446b20a9..58c70cc7f0 100644 --- a/sources/Renderer/OpenGL/Buffer/GLVertexArrayObject.h +++ b/sources/Renderer/OpenGL/Buffer/GLVertexArrayObject.h @@ -18,6 +18,23 @@ namespace LLGL struct VertexAttribute; +class GLStateManager; + +struct GLVertexAttribute +{ + GLuint buffer; + GLuint index; + GLint size; + GLenum type; + GLboolean normalized; + GLsizei stride; + GLsizeiptr offsetPtrSized; + GLuint divisor; // for use with glVertexAttribDivisor() + bool isInteger; // meta data for use with glVertexAttribIPointer() +}; + +// Converts the specified vertex attribute into a GL specific attributes. +void GLConvertVertexAttrib(GLVertexAttribute& dst, const VertexAttribute& src, GLuint srcBuffer); // Wrapper class for an OpenGL Vertex-Array-Object (VAO), for GL 3.0+. class GLVertexArrayObject @@ -25,11 +42,11 @@ class GLVertexArrayObject public: - GLVertexArrayObject(); - ~GLVertexArrayObject(); + // Release VAO from GL context. + void Release(); // Builds the specified attribute using a 'glVertexAttrib*Pointer' function. - void BuildVertexLayout(const ArrayView& attributes); + void BuildVertexLayout(const ArrayView& attributes); // Returns the ID of the hardware vertex-array-object (VAO) inline GLuint GetID() const @@ -39,7 +56,7 @@ class GLVertexArrayObject private: - void BuildVertexAttribute(const VertexAttribute& attribute); + void BuildVertexAttribute(const GLVertexAttribute& attribute); private: diff --git a/sources/Renderer/OpenGL/CMakeLists.txt b/sources/Renderer/OpenGL/CMakeLists.txt index 9dbe4f534a..67e6551f05 100644 --- a/sources/Renderer/OpenGL/CMakeLists.txt +++ b/sources/Renderer/OpenGL/CMakeLists.txt @@ -46,11 +46,6 @@ find_source_files(FilesIncludeGL INC ${BACKEND_INCLUDE_DIR}/OpenG # Remove selected files if GL2X is disabled if(NOT LLGL_GL_ENABLE_OPENGL2X) - list( - REMOVE_ITEM FilesRendererGLBuffer - "${PROJECT_SOURCE_DIR}/Buffer/GL2XVertexArray.cpp" - "${PROJECT_SOURCE_DIR}/Buffer/GL2XVertexArray.h" - ) list( REMOVE_ITEM FilesRendererGLTexture "${PROJECT_SOURCE_DIR}/Texture/GL2XSampler.cpp" diff --git a/sources/Renderer/OpenGL/Command/GLCommand.h b/sources/Renderer/OpenGL/Command/GLCommand.h index 021ac8a869..2c6a26ea14 100644 --- a/sources/Renderer/OpenGL/Command/GLCommand.h +++ b/sources/Renderer/OpenGL/Command/GLCommand.h @@ -32,8 +32,8 @@ class GLSwapChain; class GLRenderTarget; class GLRenderPass; class GLDeferredCommandBuffer; +class GLSharedContextVertexArray; #ifdef LLGL_GL_ENABLE_OPENGL2X -class GL2XVertexArray; class GL2XSampler; #endif @@ -181,16 +181,9 @@ struct GLCmdClearBuffers struct GLCmdBindVertexArray { - GLuint vao; + GLSharedContextVertexArray* vertexArray; }; -#ifdef LLGL_GL_ENABLE_OPENGL2X -struct GLCmdBindGL2XVertexArray -{ - const GL2XVertexArray* vertexArrayGL2X; -}; -#endif - struct GLCmdBindElementArrayBufferToVAO { GLuint id; diff --git a/sources/Renderer/OpenGL/Command/GLCommandAssembler.cpp b/sources/Renderer/OpenGL/Command/GLCommandAssembler.cpp index 2b6c04b420..7a59ff56d8 100644 --- a/sources/Renderer/OpenGL/Command/GLCommandAssembler.cpp +++ b/sources/Renderer/OpenGL/Command/GLCommandAssembler.cpp @@ -196,17 +196,9 @@ static std::size_t AssembleGLCommand(const GLOpcode opcode, const void* pc, JITC case GLOpcodeBindVertexArray: { auto cmd = reinterpret_cast(pc); - compiler.CallMember(&GLStateManager::BindVertexArray, g_stateMngrArg, cmd->vao); + compiler.CallMember(&GLSharedContextVertexArray::Bind, cmd->vertexArray, g_stateMngrArg); return sizeof(*cmd); } - #ifdef LLGL_GL_ENABLE_OPENGL2X - case GLOpcodeBindGL2XVertexArray: - { - auto cmd = reinterpret_cast(pc); - compiler.CallMember(&GL2XVertexArray::Bind, cmd->vertexArrayGL2X, g_stateMngrArg); - return sizeof(*cmd); - } - #endif case GLOpcodeBindElementArrayBufferToVAO: { auto cmd = reinterpret_cast(pc); diff --git a/sources/Renderer/OpenGL/Command/GLCommandExecutor.cpp b/sources/Renderer/OpenGL/Command/GLCommandExecutor.cpp index 65395d7652..7c9a0641aa 100644 --- a/sources/Renderer/OpenGL/Command/GLCommandExecutor.cpp +++ b/sources/Renderer/OpenGL/Command/GLCommandExecutor.cpp @@ -195,17 +195,9 @@ static std::size_t ExecuteGLCommand(const GLOpcode opcode, const void* pc, GLSta case GLOpcodeBindVertexArray: { auto cmd = reinterpret_cast(pc); - stateMngr->BindVertexArray(cmd->vao); + cmd->vertexArray->Bind(*stateMngr); return sizeof(*cmd); } - #ifdef LLGL_GL_ENABLE_OPENGL2X - case GLOpcodeBindGL2XVertexArray: - { - auto cmd = reinterpret_cast(pc); - cmd->vertexArrayGL2X->Bind(*stateMngr); - return sizeof(*cmd); - } - #endif case GLOpcodeBindElementArrayBufferToVAO: { auto cmd = reinterpret_cast(pc); diff --git a/sources/Renderer/OpenGL/Command/GLCommandOpcode.h b/sources/Renderer/OpenGL/Command/GLCommandOpcode.h index c695f5c4ef..65fde3e626 100644 --- a/sources/Renderer/OpenGL/Command/GLCommandOpcode.h +++ b/sources/Renderer/OpenGL/Command/GLCommandOpcode.h @@ -40,7 +40,6 @@ enum GLOpcode : std::uint8_t GLOpcodeClearAttachmentsWithRenderPass, GLOpcodeClearBuffers, GLOpcodeBindVertexArray, - GLOpcodeBindGL2XVertexArray, GLOpcodeBindElementArrayBufferToVAO, GLOpcodeBindBufferBase, GLOpcodeBindBuffersBase, diff --git a/sources/Renderer/OpenGL/Command/GLDeferredCommandBuffer.cpp b/sources/Renderer/OpenGL/Command/GLDeferredCommandBuffer.cpp index e6572c6326..4dc2812d83 100644 --- a/sources/Renderer/OpenGL/Command/GLDeferredCommandBuffer.cpp +++ b/sources/Renderer/OpenGL/Command/GLDeferredCommandBuffer.cpp @@ -359,19 +359,9 @@ void GLDeferredCommandBuffer::SetVertexBuffer(Buffer& buffer) { if ((buffer.GetBindFlags() & BindFlags::VertexBuffer) != 0) { - auto& bufferWithVAO = LLGL_CAST(const GLBufferWithVAO&, buffer); - #ifdef LLGL_GL_ENABLE_OPENGL2X - if (!HasNativeVAO()) - { - auto cmd = AllocCommand(GLOpcodeBindGL2XVertexArray); - cmd->vertexArrayGL2X = &(bufferWithVAO.GetVertexArrayGL2X()); - } - else - #endif // /LLGL_GL_ENABLE_OPENGL2X - { - auto cmd = AllocCommand(GLOpcodeBindVertexArray); - cmd->vao = bufferWithVAO.GetVaoID(); - } + auto& bufferWithVAO = LLGL_CAST(GLBufferWithVAO&, buffer); + auto cmd = AllocCommand(GLOpcodeBindVertexArray); + cmd->vertexArray = bufferWithVAO.GetVertexArray(); } } @@ -379,19 +369,9 @@ void GLDeferredCommandBuffer::SetVertexBufferArray(BufferArray& bufferArray) { if ((bufferArray.GetBindFlags() & BindFlags::VertexBuffer) != 0) { - auto& bufferArrayWithVAO = LLGL_CAST(const GLBufferArrayWithVAO&, bufferArray); - #ifdef LLGL_GL_ENABLE_OPENGL2X - if (!HasNativeVAO()) - { - auto cmd = AllocCommand(GLOpcodeBindGL2XVertexArray); - cmd->vertexArrayGL2X = &(bufferArrayWithVAO.GetVertexArrayGL2X()); - } - else - #endif - { - auto cmd = AllocCommand(GLOpcodeBindVertexArray); - cmd->vao = bufferArrayWithVAO.GetVaoID(); - } + auto& bufferArrayWithVAO = LLGL_CAST(GLBufferArrayWithVAO&, bufferArray); + auto cmd = AllocCommand(GLOpcodeBindVertexArray); + cmd->vertexArray = bufferArrayWithVAO.GetVertexArray(); } } diff --git a/sources/Renderer/OpenGL/Command/GLImmediateCommandBuffer.cpp b/sources/Renderer/OpenGL/Command/GLImmediateCommandBuffer.cpp index c4879c6837..07e849def8 100644 --- a/sources/Renderer/OpenGL/Command/GLImmediateCommandBuffer.cpp +++ b/sources/Renderer/OpenGL/Command/GLImmediateCommandBuffer.cpp @@ -290,19 +290,7 @@ void GLImmediateCommandBuffer::SetVertexBuffer(Buffer& buffer) { /* Bind vertex buffer */ auto& vertexBufferGL = LLGL_CAST(GLBufferWithVAO&, buffer); - - #ifdef LLGL_GL_ENABLE_OPENGL2X - if (!HasNativeVAO()) - { - /* Bind vertex array with emulator (for GL 2.x compatibility) */ - vertexBufferGL.GetVertexArrayGL2X().Bind(*stateMngr_); - } - else - #endif // /LLGL_GL_ENABLE_OPENGL2X - { - /* Bind vertex array with native VAO */ - stateMngr_->BindVertexArray(vertexBufferGL.GetVaoID()); - } + vertexBufferGL.GetVertexArray()->Bind(*stateMngr_); } } @@ -312,19 +300,7 @@ void GLImmediateCommandBuffer::SetVertexBufferArray(BufferArray& bufferArray) { /* Bind vertex buffer */ auto& vertexBufferArrayGL = LLGL_CAST(GLBufferArrayWithVAO&, bufferArray); - - #ifdef LLGL_GL_ENABLE_OPENGL2X - if (!HasNativeVAO()) - { - /* Bind vertex array with emulator (for GL 2.x compatibility) */ - vertexBufferArrayGL.GetVertexArrayGL2X().Bind(*stateMngr_); - } - else - #endif // /LLGL_GL_ENABLE_OPENGL2X - { - /* Bind vertex array with native VAO */ - stateMngr_->BindVertexArray(vertexBufferArrayGL.GetVaoID()); - } + vertexBufferArrayGL.GetVertexArray()->Bind(*stateMngr_); } } diff --git a/sources/Renderer/OpenGL/GLCoreProfile/GLCoreProfileCaps.cpp b/sources/Renderer/OpenGL/GLCoreProfile/GLCoreProfileCaps.cpp index 9dc16f51f7..19bc94b107 100644 --- a/sources/Renderer/OpenGL/GLCoreProfile/GLCoreProfileCaps.cpp +++ b/sources/Renderer/OpenGL/GLCoreProfile/GLCoreProfileCaps.cpp @@ -385,6 +385,45 @@ void GLQueryRenderingCaps(RenderingCapabilities& caps) GLGetTextureLimits(caps.features, caps.limits); } +static void AppendCacheIDBytes(std::vector& cacheID, const void* bytes, std::size_t count) +{ + const std::size_t offset = cacheID.size(); + cacheID.resize(offset + count); + ::memcpy(&cacheID[offset], bytes, count); +} + +template +static void AppendCacheIDValue(std::vector& cacheID, const T& val) +{ + AppendCacheIDBytes(cacheID, &val, sizeof(val)); +} + +void GLQueryPipelineCacheID(std::vector& cacheID) +{ + #ifdef GL_ARB_get_program_binary + if (HasExtension(GLExt::ARB_get_program_binary)) + { + GLint numBinaryFormats = 0; + glGetIntegerv(GL_NUM_PROGRAM_BINARY_FORMATS, &numBinaryFormats); + if (numBinaryFormats > 0) + { + /* Append number of binary formats */ + AppendCacheIDValue(cacheID, numBinaryFormats); + + /* Append binary format values themselves */ + std::vector formats; + formats.resize(numBinaryFormats); + glGetIntegerv(GL_PROGRAM_BINARY_FORMATS, formats.data()); + AppendCacheIDBytes(cacheID, formats.data(), sizeof(GLint) * formats.size()); + + /* Append GL version string */ + if (const GLubyte* versionStr = glGetString(GL_VERSION)) + AppendCacheIDBytes(cacheID, versionStr, ::strlen(reinterpret_cast(versionStr))); + } + } + #endif // /GL_ARB_get_program_binary +} + } // /namespace LLGL diff --git a/sources/Renderer/OpenGL/GLRenderSystem.cpp b/sources/Renderer/OpenGL/GLRenderSystem.cpp index e854cd1ed2..8c51f8805a 100644 --- a/sources/Renderer/OpenGL/GLRenderSystem.cpp +++ b/sources/Renderer/OpenGL/GLRenderSystem.cpp @@ -177,7 +177,7 @@ GLBuffer* GLRenderSystem::CreateGLBuffer(const BufferDescriptor& bufferDesc, con auto* bufferGL = buffers_.emplace(bufferDesc.bindFlags, bufferDesc.debugName); { GLBufferStorage(*bufferGL, bufferDesc, initialData); - bufferGL->BuildVertexArray(bufferDesc.vertexAttribs.size(), bufferDesc.vertexAttribs.data()); + bufferGL->BuildVertexArray(bufferDesc.vertexAttribs); } return bufferGL; } @@ -430,23 +430,10 @@ void GLRenderSystem::Release(RenderPass& renderPass) /* ----- Render Targets ----- */ -static GLPixelFormat GetGLPixelFormatForRenderTargetDesc(const RenderTargetDescriptor& renderTargetDesc) -{ - GLPixelFormat pixelFormat; - { - pixelFormat.colorBits = 32; - const Format depthStencilFormat = GetAttachmentFormat(renderTargetDesc.depthStencilAttachment); - GetFormatBits(depthStencilFormat, nullptr, &(pixelFormat.depthBits), &(pixelFormat.stencilBits)); - pixelFormat.samples = static_cast(std::max(1, renderTargetDesc.samples)); - } - return pixelFormat; -} - RenderTarget* GLRenderSystem::CreateRenderTarget(const RenderTargetDescriptor& renderTargetDesc) { /* Make sure we have a GLContext with compatible resolution */ - const GLPixelFormat pixelFormat = GetGLPixelFormatForRenderTargetDesc(renderTargetDesc); - CreateGLContextWithPixelFormatOnce(pixelFormat); + CreateGLContextOnce(); LLGL_ASSERT_RENDERING_FEATURE_SUPPORT(hasRenderTargets); return renderTargets_.emplace(GetRenderingCaps().limits, renderTargetDesc); } @@ -598,12 +585,7 @@ void GLRenderSystem::CreateGLContextOnce() (void)contextMngr_.AllocContext(); } -void GLRenderSystem::CreateGLContextWithPixelFormatOnce(const GLPixelFormat& pixelFormat) -{ - (void)contextMngr_.AllocContext(&pixelFormat, /*acceptCompatibleFormat:*/ true); -} - -void GLRenderSystem::RegisterNewGLContext(GLContext& /*context*/, const GLPixelFormat& /*pixelFormat*/) +void GLRenderSystem::RegisterNewGLContext(GLContext& /*context*/, const GLPixelFormat& pixelFormat) { /* Enable debug callback function */ if (debugContext_) @@ -669,45 +651,6 @@ static std::string GLGetString(GLenum name) return (bytes != nullptr ? std::string(reinterpret_cast(bytes)) : ""); } -static void AppendCacheIDBytes(std::vector& cacheID, const void* bytes, std::size_t count) -{ - const std::size_t offset = cacheID.size(); - cacheID.resize(offset + count); - ::memcpy(&cacheID[offset], bytes, count); -} - -template -static void AppendCacheIDValue(std::vector& cacheID, const T& val) -{ - AppendCacheIDBytes(cacheID, &val, sizeof(val)); -} - -static void GLQueryPipelineCacheID(std::vector& cacheID) -{ - #ifdef GL_ARB_get_program_binary - if (HasExtension(GLExt::ARB_get_program_binary)) - { - GLint numBinaryFormats = 0; - glGetIntegerv(GL_NUM_PROGRAM_BINARY_FORMATS, &numBinaryFormats); - if (numBinaryFormats > 0) - { - /* Append number of binary formats */ - AppendCacheIDValue(cacheID, numBinaryFormats); - - /* Append binary format values themselves */ - std::vector formats; - formats.resize(numBinaryFormats); - glGetIntegerv(GL_PROGRAM_BINARY_FORMATS, formats.data()); - AppendCacheIDBytes(cacheID, formats.data(), sizeof(GLint) * formats.size()); - - /* Append GL version string */ - if (const GLubyte* versionStr = glGetString(GL_VERSION)) - AppendCacheIDBytes(cacheID, versionStr, ::strlen(reinterpret_cast(versionStr))); - } - } - #endif // /GL_ARB_get_program_binary -} - static void GLQueryRendererInfo(RendererInfo& info) { info.rendererName = GLProfile::GetAPIName() + std::string(" ") + GLGetString(GL_VERSION); diff --git a/sources/Renderer/OpenGL/GLRenderSystem.h b/sources/Renderer/OpenGL/GLRenderSystem.h index 0abcf24002..5592f09e87 100644 --- a/sources/Renderer/OpenGL/GLRenderSystem.h +++ b/sources/Renderer/OpenGL/GLRenderSystem.h @@ -74,7 +74,6 @@ class GLRenderSystem final : public RenderSystem // Creates a GL context once or creates a new one if there is no compatible one with the specified pixel format. void CreateGLContextOnce(); - void CreateGLContextWithPixelFormatOnce(const GLPixelFormat& pixelFormat); // Updates the renderer capabilities information and enables the debug layer for the new GLContext if enabled. void RegisterNewGLContext(GLContext& context, const GLPixelFormat& pixelFormat); diff --git a/sources/Renderer/OpenGL/GLStaticAssertions.cpp b/sources/Renderer/OpenGL/GLStaticAssertions.cpp index b6e7a97598..aa988162f4 100644 --- a/sources/Renderer/OpenGL/GLStaticAssertions.cpp +++ b/sources/Renderer/OpenGL/GLStaticAssertions.cpp @@ -48,9 +48,6 @@ LLGL_ASSERT_STDLAYOUT_STRUCT( GLCmdClear ); LLGL_ASSERT_STDLAYOUT_STRUCT( GLCmdClearAttachmentsWithRenderPass ); LLGL_ASSERT_STDLAYOUT_STRUCT( GLCmdClearBuffers ); LLGL_ASSERT_STDLAYOUT_STRUCT( GLCmdBindVertexArray ); -#ifdef LLGL_GL_ENABLE_OPENGL2X -LLGL_ASSERT_STDLAYOUT_STRUCT( GLCmdBindGL2XVertexArray ); -#endif LLGL_ASSERT_STDLAYOUT_STRUCT( GLCmdBindElementArrayBufferToVAO ); LLGL_ASSERT_STDLAYOUT_STRUCT( GLCmdBindBufferBase ); LLGL_ASSERT_STDLAYOUT_STRUCT( GLCmdBindBuffersBase ); diff --git a/sources/Renderer/OpenGL/Platform/GLContext.h b/sources/Renderer/OpenGL/Platform/GLContext.h index bde1018dde..93fec0c2a0 100644 --- a/sources/Renderer/OpenGL/Platform/GLContext.h +++ b/sources/Renderer/OpenGL/Platform/GLContext.h @@ -97,7 +97,7 @@ class GLContext // Returns a pointer to the current GL context. static GLContext* GetCurrent(); - // Returns the global index of the current GL context (). + // Returns the global index of the current GL context. 0 denotes an invalid index. static unsigned GetCurrentGlobalIndex(); // Sets the swap interval for the current GL context. diff --git a/sources/Renderer/OpenGL/Platform/GLContextManager.cpp b/sources/Renderer/OpenGL/Platform/GLContextManager.cpp index 3eeee41f63..4e036ff78d 100644 --- a/sources/Renderer/OpenGL/Platform/GLContextManager.cpp +++ b/sources/Renderer/OpenGL/Platform/GLContextManager.cpp @@ -106,6 +106,9 @@ std::shared_ptr GLContextManager::MakeContextWithPixelFormat(const GL stateMngr.DetermineExtensionsAndLimits(); InitRenderStates(stateMngr); + /* Cache new context as the current one */ + GLContext::SetCurrent(context.get()); + /* Invoke callback to register new GLContext */ if (newContextCallback_) newContextCallback_(*context, pixelFormat); diff --git a/sources/Renderer/RenderTargetUtils.cpp b/sources/Renderer/RenderTargetUtils.cpp index f9d792e745..dc2b1b5a8f 100644 --- a/sources/Renderer/RenderTargetUtils.cpp +++ b/sources/Renderer/RenderTargetUtils.cpp @@ -32,46 +32,6 @@ LLGL_EXPORT Format GetAttachmentFormat(const AttachmentDescriptor& attachmentDes return Format::Undefined; } -static void SetFormatBits( - std::uint32_t inColorBits, - std::uint32_t inDepthBits, - std::uint32_t inStencilBits, - int* outColorBits, - int* outDepthBits, - int* outStencilBits) -{ - if (outColorBits != nullptr) - *outColorBits = static_cast(inColorBits); - if (outDepthBits != nullptr) - *outDepthBits = static_cast(inDepthBits); - if (outStencilBits != nullptr) - *outStencilBits = static_cast(inStencilBits); -} - -LLGL_EXPORT std::uint32_t GetFormatBits(Format format, int* outColorBits, int* outDepthBits, int* outStencilBits) -{ - const FormatAttributes& attribs = GetFormatAttribs(format); - switch (format) - { - case Format::D16UNorm: - SetFormatBits(0u, 16, 0u, outColorBits, outDepthBits, outStencilBits); - break; - case Format::D24UNormS8UInt: - SetFormatBits(0u, 24u, 8u, outColorBits, outDepthBits, outStencilBits); - break; - case Format::D32Float: - SetFormatBits(0u, 32u, 0u, outColorBits, outDepthBits, outStencilBits); - break; - case Format::D32FloatS8X24UInt: - SetFormatBits(0u, 32u, 8u, outColorBits, outDepthBits, outStencilBits); - break; - default: - SetFormatBits(attribs.bitSize, 0u, 0u, outColorBits, outDepthBits, outStencilBits); - break; - } - return attribs.bitSize; -} - LLGL_EXPORT std::uint32_t NumActiveColorAttachments(const RenderTargetDescriptor& renderTargetDesc) { std::uint32_t n = 0; diff --git a/sources/Renderer/RenderTargetUtils.h b/sources/Renderer/RenderTargetUtils.h index 2622f1a34a..d57d2b5d8d 100644 --- a/sources/Renderer/RenderTargetUtils.h +++ b/sources/Renderer/RenderTargetUtils.h @@ -30,14 +30,6 @@ LLGL_EXPORT bool IsAttachmentEnabled(const AttachmentDescriptor& attachmentDesc) // Returns the format of the specified render-target attachment. LLGL_EXPORT Format GetAttachmentFormat(const AttachmentDescriptor& attachmentDesc); -/* -Returns the bitcount for color, depth, and stencil the format of the specified render-target attachment provides. -Return value is the total number of bits and individual components can be returned via their output parameters. -This total number of bits might be larger than the sum of the individual bits, since some formats have unused components (such as Format::D32FloatS8X24UInt). -These are standard integers instead of \c std::uint32_t to be used with the SwapChainDescriptor and other internal structures. -*/ -LLGL_EXPORT std::uint32_t GetFormatBits(Format format, int* outColorBits = nullptr, int* outDepthBits = nullptr, int* outStencilBits = nullptr); - /* Returns the number of active color attachments in the specified render target descriptor. The first inactive attachment breaks the count.