58 wxString vendor( glGetString( GL_VENDOR ) );
64 if( vendor.StartsWith(
"Intel" ) || vendor.Contains(
"etnaviv" ) )
69#ifdef KICAD_GAL_PROFILE
76 glBindBuffer( GL_ARRAY_BUFFER, 0 );
77 checkGlError(
"allocating video memory for cached container", __FILE__, __LINE__ );
105 throw std::runtime_error(
"OpenGL no longer available!" );
108 m_vertices =
static_cast<VERTEX*
>( glMapBuffer( GL_ARRAY_BUFFER, GL_READ_WRITE ) );
110 if(
checkGlError(
"mapping vertices buffer", __FILE__, __LINE__ ) == GL_NO_ERROR
118 glBindBuffer( GL_ARRAY_BUFFER, 0 );
119 throw std::runtime_error(
"Could not map vertex buffer: glMapBuffer returned null" );
132 glUnmapBuffer( GL_ARRAY_BUFFER );
133 checkGlError(
"unmapping vertices buffer", __FILE__, __LINE__ );
134 glBindBuffer( GL_ARRAY_BUFFER, 0 );
136 checkGlError(
"unbinding vertices buffer", __FILE__, __LINE__ );
138 catch(
const std::runtime_error& err )
140 wxLogError( wxT(
"OpenGL did not shut down properly.\n\n%s" ), err.what() );
154 const size_t newBytes =
static_cast<size_t>( aNewSize ) *
VERTEX_SIZE;
159 throw KIGFX::GPU_OOM_ERROR(
"Insufficient GPU memory to render this board; switching to software rendering." );
174 wxT(
"Resizing & defragmenting container from %d to %d" ),
m_currentSize,
181#ifdef KICAD_GAL_PROFILE
188 glUnmapBuffer( GL_ARRAY_BUFFER );
191 glGenBuffers( 1, &newBuffer );
195#ifdef KICAD_GAL_PROFILE
197 glGetIntegerv( GL_ELEMENT_ARRAY_BUFFER_BINDING, &eaBuffer );
198 wxASSERT( eaBuffer == 0 );
200 glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, newBuffer );
201 glBufferData( GL_ELEMENT_ARRAY_BUFFER, aNewSize *
VERTEX_SIZE,
nullptr, GL_DYNAMIC_DRAW );
202 checkGlError(
"creating buffer during defragmentation", __FILE__, __LINE__ );
204 std::set<VERTEX_ITEM*>::iterator it, it_end;
208 for( it =
m_items.begin(), it_end =
m_items.end(); it != it_end; ++it )
212 int itemSize = item->
GetSize();
215 glCopyBufferSubData( GL_ARRAY_BUFFER, GL_ELEMENT_ARRAY_BUFFER, itemOffset *
VERTEX_SIZE,
222 newOffset += itemSize;
226 if(
m_item->GetSize() > 0 )
228 glCopyBufferSubData( GL_ARRAY_BUFFER, GL_ELEMENT_ARRAY_BUFFER,
232 m_item->setOffset( newOffset );
237 glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, 0 );
238 glBindBuffer( GL_ARRAY_BUFFER, 0 );
252 catch(
const std::runtime_error& )
259 checkGlError(
"switching buffers during defragmentation", __FILE__, __LINE__ );
261#ifdef KICAD_GAL_PROFILE
286 wxT(
"Resizing & defragmenting container (memcpy) from %d to %d" ),
m_currentSize,
293#ifdef KICAD_GAL_PROFILE
301 glGenBuffers( 1, &newBuffer );
305#ifdef KICAD_GAL_PROFILE
307 glGetIntegerv( GL_ELEMENT_ARRAY_BUFFER_BINDING, &eaBuffer );
308 wxASSERT( eaBuffer == 0 );
311 glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, newBuffer );
312 glBufferData( GL_ELEMENT_ARRAY_BUFFER, aNewSize *
VERTEX_SIZE,
nullptr, GL_DYNAMIC_DRAW );
313 newBufferMem =
static_cast<VERTEX*
>( glMapBuffer( GL_ELEMENT_ARRAY_BUFFER, GL_WRITE_ONLY ) );
314 checkGlError(
"creating buffer during defragmentation", __FILE__, __LINE__ );
316 if( newBufferMem ==
nullptr )
318 glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, 0 );
319 glDeleteBuffers( 1, &newBuffer );
326 glUnmapBuffer( GL_ELEMENT_ARRAY_BUFFER );
327 glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, 0 );
338 catch(
const std::runtime_error& )
345 checkGlError(
"switching buffers during defragmentation", __FILE__, __LINE__ );
347#ifdef KICAD_GAL_PROFILE
372 wxT(
"Resizing & defragmenting container (RAM staged) from %d to %d" ),
379 const unsigned int usedVerts =
usedSpace();
383 std::unique_ptr<VERTEX[]> staging;
387 staging.reset(
new VERTEX[usedVerts] );
389 catch(
const std::bad_alloc& )
391 throw GPU_OOM_ERROR(
"Out of memory while staging a GPU buffer resize; "
392 "switching to software rendering." );
402 glGenBuffers( 1, &newBuffer );
403 glBindBuffer( GL_ARRAY_BUFFER, newBuffer );
404 glBufferData( GL_ARRAY_BUFFER, aNewSize *
VERTEX_SIZE,
nullptr, GL_DYNAMIC_DRAW );
405 glBindBuffer( GL_ARRAY_BUFFER, 0 );
406 checkGlError(
"allocating staged buffer during defragmentation", __FILE__, __LINE__ );
414 catch(
const std::runtime_error& )
423 checkGlError(
"switching buffers during staged defragmentation", __FILE__, __LINE__ );
440 unsigned int size = 0;
442 for(
const auto& item :
m_items )
444 size += item->GetSize();
void Map() override
Prepare the container for vertices updates.
bool m_isMapped
Flag saying if vertex buffer is currently mapped.
bool m_useCopyBuffer
Flag saying whether it is safe to use glCopyBufferSubData.
virtual unsigned int AllItemsSize() const override
void Abandon() override
Give up ownership of any GL objects without deleting them.
bool IsMapped() const override
Return true if vertex buffer is currently mapped.
bool defragmentResizeStaged(unsigned int aNewSize)
Grow the buffer while keeping the peak video memory at max(old, new) rather than old + new,...
bool defragmentResizeMemcpy(unsigned int aNewSize)
void Unmap() override
Finish the vertices updates stage.
CACHED_CONTAINER_GPU(unsigned int aSize=DEFAULT_SIZE)
bool defragmentResize(unsigned int aNewSize) override
Remove empty spaces between chunks and optionally resizes the container.
unsigned int m_glBufferHandle
Vertex buffer handle.
unsigned int m_chunkOffset
std::set< VERTEX_ITEM * > m_items
Stored VERTEX_ITEMs.
VERTEX_ITEM * m_item
Currently modified item.
FREE_CHUNK_MAP m_freeChunks
Store size & offset of free chunks.
void defragment(VERTEX *aTarget)
Transfer all stored data to a new buffer, removing empty spaces between the data chunks in the contai...
CACHED_CONTAINER(unsigned int aSize=DEFAULT_SIZE)
Raised when a GPU buffer allocation is predicted to exceed the available video memory.
VERTEX * m_vertices
Actual storage memory.
unsigned int m_currentSize
Current container size, expressed in vertices.
unsigned int m_freeSpace
Free space left in the container, expressed in vertices.
unsigned int usedSpace() const
Return size of the used memory space.
void setOffset(unsigned int aOffset)
Set data offset in the container.
unsigned int GetOffset() const
Return data offset in the container.
unsigned int GetSize() const
Return information about number of vertices stored.
A small class to help profiling.
void Stop()
Save the time when this function was called, and set the counter stane to stop.
double msecs(bool aSinceLast=false)
static const wxChar *const traceGalCachedContainerGpu
Flag to enable debug output of the GAL OpenGL GPU cached container.
const wxChar *const traceGalProfile
Flag to enable debug output of GAL performance profiling.
The Cairo implementation of the graphics abstraction layer.
static constexpr size_t VERTEX_SIZE
@ REFUSE
Neither path fits; the caller should fall back to software rendering.
@ GPU_COPY
Fast GPU-side copy; the old and new buffers are briefly co-resident.
@ RAM_STAGE
Stage through host memory so only the larger of the two buffers is resident.
VRAM_RESIZE_STRATEGY chooseResizeStrategy(size_t aFreeVRAM, size_t aOldBytes, size_t aNewBytes, double aMarginFrac)
Decide how to grow a GPU vertex buffer given the free video memory budget.
size_t queryFreeVideoMemoryBytes()
Query the amount of free video memory the driver reports.
wxLogTrace helper definitions.
int checkGlError(const std::string &aInfo, const char *aFile, int aLine, bool aThrow)
Check if a recent OpenGL operation has failed.
Class to handle an item held in a container.