Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
91 changes: 91 additions & 0 deletions source/MRViewer/MRRenderGLHelpers.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
#include "MRRenderGLHelpers.h"
#include "MRViewer.h"
#include "MRGLMacro.h"

namespace MR
{

void GlBuffer::gen()
{
del();
GL_EXEC( glGenBuffers( 1, &bufferID_ ) );
assert( valid() );
}

void GlBuffer::del()
{
if ( !valid() )
return;
if ( Viewer::constInstance()->isGLInitialized() && loadGL() )
{
GL_EXEC( glDeleteBuffers( 1, &bufferID_ ) );
}
bufferID_ = NO_BUF;
size_ = 0;
}

void GlBuffer::bind()
{
assert( valid() );
GL_EXEC( glBindBuffer( GL_ARRAY_BUFFER, bufferID_ ) );
}

void GlBuffer::loadData( const char * arr, size_t arrSize )
{
if ( !valid() )
gen();
bind();
GLint64 bufSize = arrSize;
auto maxUploadSize = ( GLint64( 1 ) << 32 ) - 4096; //4Gb - 4096, 4Gb is already too much
if ( bufSize <= maxUploadSize )
{
// buffers less than 4Gb are ok to load immediately
GL_EXEC( glBufferData( GL_ARRAY_BUFFER, bufSize, arr, GL_DYNAMIC_DRAW ) );
}
else
{
// buffers more than 4Gb are better to split on chunks to avoid strange errors from GL or drivers
GL_EXEC( glBufferData( GL_ARRAY_BUFFER, bufSize, nullptr, GL_DYNAMIC_DRAW ) );
GLint64 remStart = 0;
auto remSize = bufSize;
for ( ; remSize > maxUploadSize; remSize -= maxUploadSize, remStart += maxUploadSize )
{
GL_EXEC( glBufferSubData( GL_ARRAY_BUFFER, remStart, maxUploadSize, arr + remStart ) );
}
GL_EXEC( glBufferSubData( GL_ARRAY_BUFFER, remStart, remSize, arr + remStart ) );
}
size_ = arrSize;
}

GLint bindVertexAttribArray( const BindVertexAttribArraySettings & settings )
{
GL_EXEC( GLint id = glGetAttribLocation( settings.program_shader, settings.name ) );
if ( id < 0 )
return id;
if ( settings.arrSize == 0 && !settings.forceUse )
{
GL_EXEC( glDisableVertexAttribArray( id ) );
settings.buf.del();
return id;
}

if ( settings.refresh )
settings.buf.loadData( settings.arr, settings.arrSize );
else
settings.buf.bind();

// GL_FLOAT is left here consciously
if ( settings.isColor )
{
GL_EXEC( glVertexAttribPointer( id, settings.baseTypeElementsNumber, GL_UNSIGNED_BYTE, GL_TRUE, 0, 0 ) );
}
else
{
GL_EXEC( glVertexAttribPointer( id, settings.baseTypeElementsNumber, GL_FLOAT, GL_FALSE, 0, 0 ) );
}

GL_EXEC( glEnableVertexAttribArray( id ) );
return id;
}

} //namespace MR
112 changes: 36 additions & 76 deletions source/MRViewer/MRRenderGLHelpers.h
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
#pragma once

#include "MRGladGlfw.h"
#include "MRGLMacro.h"
#include "MRViewer.h"
#include "exports.h"
#include "MRMesh/MRColor.h"
#include <cassert>

namespace MR
Expand All @@ -25,32 +25,18 @@ class GlBuffer
size_t size() const { return size_; }

// generates new buffer
void gen()
{
del();
GL_EXEC( glGenBuffers( 1, &bufferID_ ) );
assert( valid() );
}
MRVIEWER_API void gen();

// deletes the buffer
void del()
{
if ( !valid() )
return;
if ( Viewer::constInstance()->isGLInitialized() && loadGL() )
{
GL_EXEC( glDeleteBuffers( 1, &bufferID_ ) );
}
bufferID_ = NO_BUF;
size_ = 0;
}
MRVIEWER_API void del();

// binds current buffer to OpenGL context
void bind() { assert( valid() ); GL_EXEC( glBindBuffer( GL_ARRAY_BUFFER, bufferID_ ) ); }
MRVIEWER_API void bind();

// creates GL data buffer using given data
MRVIEWER_API void loadData( const char * arr, size_t arrSize );
template<typename T>
void loadData( const T * arr, size_t arrSize );
void loadData( const T * arr, size_t arrSize ) { loadData( (const char *)arr, sizeof( T ) * arrSize ); }

private:
/// another object takes control over the GL buffer
Expand All @@ -61,70 +47,44 @@ class GlBuffer
size_t size_ = 0;
};

template<typename T>
void GlBuffer::loadData( const T * arr, size_t arrSize )
struct BindVertexAttribArraySettings
{
if ( !valid() )
gen();
bind();
GLint64 bufSize = sizeof( T ) * arrSize;
auto maxUploadSize = ( GLint64( 1 ) << 32 ) - 4096; //4Gb - 4096, 4Gb is already too much
if ( bufSize <= maxUploadSize )
{
// buffers less than 4Gb are ok to load immediately
GL_EXEC( glBufferData( GL_ARRAY_BUFFER, bufSize, arr, GL_DYNAMIC_DRAW ) );
}
else
{
// buffers more than 4Gb are better to split on chunks to avoid strange errors from GL or drivers
GL_EXEC( glBufferData( GL_ARRAY_BUFFER, bufSize, nullptr, GL_DYNAMIC_DRAW ) );
GLint64 remStart = 0;
auto remSize = bufSize;
for ( ; remSize > maxUploadSize; remSize -= maxUploadSize, remStart += maxUploadSize )
{
GL_EXEC( glBufferSubData( GL_ARRAY_BUFFER, remStart, maxUploadSize, (const char *)arr + remStart ) );
}
GL_EXEC( glBufferSubData( GL_ARRAY_BUFFER, remStart, remSize, (const char *)arr + remStart ) );
}
size_ = size_t( bufSize );
}
GLuint program_shader = 0;
const char * name = nullptr;
GlBuffer & buf;
const char * arr = nullptr;
size_t arrSize = 0;
int baseTypeElementsNumber = 0;
bool refresh = false;
bool forceUse = false;
bool isColor = false;
};

MRVIEWER_API GLint bindVertexAttribArray( const BindVertexAttribArraySettings & settings );

template<typename T, template<typename, typename...> class C, typename... args>
GLint bindVertexAttribArray(
inline GLint bindVertexAttribArray(
const GLuint program_shader,
const std::string& name,
const char * name,
GlBuffer & buf,
const C<T, args...>& V,
int baseTypeElementsNumber,
bool refresh,
bool forceUse = false )
{
GL_EXEC( GLint id = glGetAttribLocation( program_shader, name.c_str() ) );
if ( id < 0 )
return id;
if ( V.size() == 0 && !forceUse )
BindVertexAttribArraySettings settings =
{
GL_EXEC( glDisableVertexAttribArray( id ) );
buf.del();
return id;
}

if ( refresh )
buf.loadData( V.data(), V.size() );
else
buf.bind();

// GL_FLOAT is left here consciously
if constexpr ( std::is_same_v<Color, T> )
{
GL_EXEC( glVertexAttribPointer( id, baseTypeElementsNumber, GL_UNSIGNED_BYTE, GL_TRUE, 0, 0 ) );
}
else
{
GL_EXEC( glVertexAttribPointer( id, baseTypeElementsNumber, GL_FLOAT, GL_FALSE, 0, 0 ) );
}

GL_EXEC( glEnableVertexAttribArray( id ) );
return id;
.program_shader = program_shader,
.name = name,
.buf = buf,
.arr = (const char*)V.data(),
.arrSize = sizeof(T) * V.size(),
.baseTypeElementsNumber = baseTypeElementsNumber,
.refresh = refresh,
.forceUse = forceUse,
.isColor = std::is_same_v<Color, T>
};
return bindVertexAttribArray( settings );
}
}

} //namespace MR
1 change: 1 addition & 0 deletions source/MRViewer/MRViewer.vcxproj
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
<ClCompile Include="MRObjectMeshHistory.cpp" />
<ClCompile Include="MRObjectTransformWidget.cpp" />
<ClCompile Include="MRPickHoleBorderElement.cpp" />
<ClCompile Include="MRRenderGLHelpers.cpp" />
<ClCompile Include="MRRenderHelpers.cpp" />
<ClCompile Include="MRRenderLabelObject.cpp" />
<ClCompile Include="MRRibbonButtonDrawer.cpp" />
Expand Down
3 changes: 3 additions & 0 deletions source/MRViewer/MRViewer.vcxproj.filters
Original file line number Diff line number Diff line change
Expand Up @@ -217,6 +217,9 @@
<ClCompile Include="MRViewerIO.cpp">
<Filter>IO</Filter>
</ClCompile>
<ClCompile Include="MRRenderGLHelpers.cpp">
<Filter>Render\Implementations</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="ImGuiHelpers.h">
Expand Down