Skip to content

Commit

Permalink
[GL] Refactored GLContext management in GL backend.
Browse files Browse the repository at this point in the history
- Finally create new GL contexts if another swap-chain or render-target with higher sample count is requested.
- Create a default GL context if none if exists in all the context dependeny RenderSystem::Create* functions,
  to ensure those functions can be called before a swap-chain is created.
- These changes enable the GL backend for offscreen rendering:
  An app can simply render into render-targets without ever having to create a swap-chain.

TODO: Some GL objects that are considered lightweight, such as VAOs and sync objects, cannot be shared across GL contexts
      and must hence be created for each of these contexts.
      For this reason, it is still required for LLGL to create a vertex buffer *after* the GLContext
      that is being used for rendering was created.
  • Loading branch information
LukasBanana committed Jul 4, 2024
1 parent 205ea7c commit fe9dd61
Show file tree
Hide file tree
Showing 19 changed files with 269 additions and 129 deletions.
62 changes: 39 additions & 23 deletions sources/Renderer/OpenGL/Buffer/GL2XVertexArray.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,30 +17,61 @@ namespace LLGL
{


void GL2XVertexArray::BuildVertexLayout(GLuint bufferID, const ArrayView<VertexAttribute>& 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 */
auto isNormalizedFormat = IsNormalizedFormat(attribute.format);
auto isFloatFormat = IsFloatFormat(attribute.format);
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 auto& formatAttribs = GetFormatAttribs(attribute.format);
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) */
auto dataType = GLTypes::Map(formatAttribs.dataType);
auto components = static_cast<GLint>(formatAttribs.components);
auto attribIndex = static_cast<GLuint>(attribute.location);
auto stride = static_cast<GLsizei>(attribute.stride);
auto offsetPtrSized = static_cast<GLsizeiptr>(attribute.offset);
GLenum dataType = GLTypes::Map(formatAttribs.dataType);
GLint components = static_cast<GLint>(formatAttribs.components);
GLuint attribIndex = static_cast<GLuint>(attribute.location);
GLsizei stride = static_cast<GLsizei>(attribute.stride);
GLsizeiptr offsetPtrSized = static_cast<GLsizeiptr>(attribute.offset);

attribs_.push_back(
{
Expand Down Expand Up @@ -89,21 +120,6 @@ void GL2XVertexArray::Finalize()
);
}

void GL2XVertexArray::Bind(GLStateManager& stateMngr) const
{
/* Enable required vertex arrays */
for (const auto& 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_);
}


} // /namespace LLGL

Expand Down
13 changes: 8 additions & 5 deletions sources/Renderer/OpenGL/Buffer/GL2XVertexArray.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@


#include <LLGL/VertexAttribute.h>
#include <LLGL/Container/ArrayView.h>
#include "../OpenGL.h"
#include <vector>

Expand All @@ -26,11 +27,8 @@ class GL2XVertexArray

public:

// Builds the specified attribute using a 'glVertexAttrib*Pointer' function.
void BuildVertexAttribute(GLuint bufferID, const VertexAttribute& attribute);

// Finalizes building vertex attributes.
void Finalize();
// Stores the vertex attributes for later use via glVertexAttrib*Pointer() functions.
void BuildVertexLayout(GLuint bufferID, const ArrayView<VertexAttribute>& attributes);

// Binds this vertex array.
void Bind(GLStateManager& stateMngr) const;
Expand All @@ -48,6 +46,11 @@ class GL2XVertexArray
const GLvoid* pointer;
};

private:

void BuildVertexAttribute(GLuint bufferID, const VertexAttribute& attribute);
void Finalize();

private:

std::vector<GL2XVertexAttrib> attribs_;
Expand Down
15 changes: 4 additions & 11 deletions sources/Renderer/OpenGL/Buffer/GLBufferArrayWithVAO.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -68,13 +68,10 @@ void GLBufferArrayWithVAO::BuildVertexArrayWithVAO(std::uint32_t numBuffers, Buf
{
if ((bufferGL->GetBindFlags() & BindFlags::VertexBuffer) != 0)
{
/* Bind VBO */
/* Bind VBO and build vertex layout */
auto* vertexBufferGL = LLGL_CAST(GLBufferWithVAO*, bufferGL);
GLStateManager::Get().BindBuffer(GLBufferTarget::ArrayBuffer, vertexBufferGL->GetID());

/* Build each vertex attribute */
for (const VertexAttribute& attrib : vertexBufferGL->GetVertexAttribs())
vao_.BuildVertexAttribute(attrib);
vao_.BuildVertexLayout(vertexBufferGL->GetVertexAttribs());
}
else
ThrowNoVertexBufferErr();
Expand All @@ -91,12 +88,8 @@ void GLBufferArrayWithVAO::BuildVertexArrayWithEmulator(std::uint32_t numBuffers
{
if (((*bufferArray)->GetBindFlags() & BindFlags::VertexBuffer) != 0)
{
auto vertexBufferGL = LLGL_CAST(GLBufferWithVAO*, (*bufferArray++));

/* Build each vertex attribute */
const auto& vertexAttribs = vertexBufferGL->GetVertexAttribs();
for (const auto& attrib : vertexAttribs)
vertexArrayGL2X_.BuildVertexAttribute(vertexBufferGL->GetID(), attrib);
auto* vertexBufferGL = LLGL_CAST(GLBufferWithVAO*, (*bufferArray++));
vertexArrayGL2X_.BuildVertexLayout(vertexBufferGL->GetID(), vertexBufferGL->GetVertexAttribs());
}
else
ThrowNoVertexBufferErr();
Expand Down
13 changes: 3 additions & 10 deletions sources/Renderer/OpenGL/Buffer/GLBufferWithVAO.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -48,15 +48,11 @@ void GLBufferWithVAO::BuildVertexArray(std::size_t numVertexAttribs, const Verte

void GLBufferWithVAO::BuildVertexArrayWithVAO()
{
/* Bind VAO */
/* Bind VAO and build vertex layout */
GLStateManager::Get().BindVertexArray(GetVaoID());
{
/* Bind VBO */
GLStateManager::Get().BindBuffer(GLBufferTarget::ArrayBuffer, GetID());

/* Build each vertex attribute */
for (const auto& attrib : vertexAttribs_)
vao_.BuildVertexAttribute(attrib);
vao_.BuildVertexLayout(vertexAttribs_);
}
GLStateManager::Get().BindVertexArray(0);
}
Expand All @@ -65,10 +61,7 @@ void GLBufferWithVAO::BuildVertexArrayWithVAO()

void GLBufferWithVAO::BuildVertexArrayWithEmulator()
{
/* Build each vertex attribute */
for (const auto& attrib : vertexAttribs_)
vertexArrayGL2X_.BuildVertexAttribute(GetID(), attrib);
vertexArrayGL2X_.Finalize();
vertexArrayGL2X_.BuildVertexLayout(GetID(), vertexAttribs_);
}

#endif // /LLGL_GL_ENABLE_OPENGL2X
Expand Down
11 changes: 11 additions & 0 deletions sources/Renderer/OpenGL/Buffer/GLVertexArrayObject.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,17 @@ GLVertexArrayObject::~GLVertexArrayObject()
}
}

void GLVertexArrayObject::BuildVertexLayout(const ArrayView<VertexAttribute>& attributes)
{
for (const VertexAttribute& attrib : attributes)
BuildVertexAttribute(attrib);
}


/*
* ======= Private: =======
*/

void GLVertexArrayObject::BuildVertexAttribute(const VertexAttribute& attribute)
{
LLGL_ASSERT_GL_EXT(ARB_vertex_array_object);
Expand Down
7 changes: 6 additions & 1 deletion sources/Renderer/OpenGL/Buffer/GLVertexArrayObject.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@


#include "../OpenGL.h"
#include <LLGL/Container/ArrayView.h>


namespace LLGL
Expand All @@ -28,14 +29,18 @@ class GLVertexArrayObject
~GLVertexArrayObject();

// Builds the specified attribute using a 'glVertexAttrib*Pointer' function.
void BuildVertexAttribute(const VertexAttribute& attribute);
void BuildVertexLayout(const ArrayView<VertexAttribute>& attributes);

// Returns the ID of the hardware vertex-array-object (VAO)
inline GLuint GetID() const
{
return id_;
}

private:

void BuildVertexAttribute(const VertexAttribute& attribute);

private:

GLuint id_ = 0; //!< Vertex array object ID.
Expand Down
7 changes: 1 addition & 6 deletions sources/Renderer/OpenGL/Command/GLCommandQueue.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,11 +23,6 @@ namespace LLGL
{


GLCommandQueue::GLCommandQueue(GLStateManager& stateManager) :
stateMngr_ { stateManager }
{
}

/* ----- Command Buffers ----- */

void GLCommandQueue::Submit(CommandBuffer& commandBuffer)
Expand All @@ -40,7 +35,7 @@ void GLCommandQueue::Submit(CommandBuffer& commandBuffer)
if (!cmdBufferGL.IsImmediateCmdBuffer())
{
auto& deferredCmdBufferGL = LLGL_CAST(const GLDeferredCommandBuffer&, cmdBufferGL);
ExecuteGLDeferredCommandBuffer(deferredCmdBufferGL, stateMngr_);
ExecuteGLDeferredCommandBuffer(deferredCmdBufferGL, GLStateManager::Get());
}
}

Expand Down
8 changes: 0 additions & 8 deletions sources/Renderer/OpenGL/Command/GLCommandQueue.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,14 +26,6 @@ class GLCommandQueue final : public CommandQueue

#include <LLGL/Backend/CommandQueue.inl>

public:

GLCommandQueue(GLStateManager& stateManager);

private:

GLStateManager& stateMngr_;

};


Expand Down
5 changes: 3 additions & 2 deletions sources/Renderer/OpenGL/Command/GLImmediateCommandBuffer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -51,15 +51,16 @@ namespace LLGL
{


GLImmediateCommandBuffer::GLImmediateCommandBuffer(GLStateManager& stateManager) :
stateMngr_ { &stateManager }
GLImmediateCommandBuffer::GLImmediateCommandBuffer() :
stateMngr_ { &(GLStateManager::Get()) }
{
}

/* ----- Encoding ----- */

void GLImmediateCommandBuffer::Begin()
{
stateMngr_ = &(GLStateManager::Get());
ResetRenderState();
}

Expand Down
2 changes: 1 addition & 1 deletion sources/Renderer/OpenGL/Command/GLImmediateCommandBuffer.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ class GLImmediateCommandBuffer final : public GLCommandBuffer

public:

GLImmediateCommandBuffer(GLStateManager& stateManager);
GLImmediateCommandBuffer();

public:

Expand Down
Loading

0 comments on commit fe9dd61

Please sign in to comment.