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__ );
97 throw std::runtime_error(
"OpenGL no longer available!" );
100 m_vertices =
static_cast<VERTEX*
>( glMapBuffer( GL_ARRAY_BUFFER, GL_READ_WRITE ) );
102 if(
checkGlError(
"mapping vertices buffer", __FILE__, __LINE__ ) == GL_NO_ERROR
110 glBindBuffer( GL_ARRAY_BUFFER, 0 );
111 throw std::runtime_error(
"Could not map vertex buffer: glMapBuffer returned null" );
124 glUnmapBuffer( GL_ARRAY_BUFFER );
125 checkGlError(
"unmapping vertices buffer", __FILE__, __LINE__ );
126 glBindBuffer( GL_ARRAY_BUFFER, 0 );
128 checkGlError(
"unbinding vertices buffer", __FILE__, __LINE__ );
130 catch(
const std::runtime_error& err )
132 wxLogError( wxT(
"OpenGL did not shut down properly.\n\n%s" ), err.what() );
146 const size_t newBytes =
static_cast<size_t>( aNewSize ) *
VERTEX_SIZE;
153 "switching to software rendering." );
168 wxT(
"Resizing & defragmenting container from %d to %d" ),
m_currentSize,
175#ifdef KICAD_GAL_PROFILE
182 glUnmapBuffer( GL_ARRAY_BUFFER );
185 glGenBuffers( 1, &newBuffer );
189#ifdef KICAD_GAL_PROFILE
191 glGetIntegerv( GL_ELEMENT_ARRAY_BUFFER_BINDING, &eaBuffer );
192 wxASSERT( eaBuffer == 0 );
194 glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, newBuffer );
195 glBufferData( GL_ELEMENT_ARRAY_BUFFER, aNewSize *
VERTEX_SIZE,
nullptr, GL_DYNAMIC_DRAW );
196 checkGlError(
"creating buffer during defragmentation", __FILE__, __LINE__ );
198 ITEMS::iterator it, it_end;
202 for( it =
m_items.begin(), it_end =
m_items.end(); it != it_end; ++it )
206 int itemSize = item->
GetSize();
209 glCopyBufferSubData( GL_ARRAY_BUFFER, GL_ELEMENT_ARRAY_BUFFER, itemOffset *
VERTEX_SIZE,
216 newOffset += itemSize;
220 if(
m_item->GetSize() > 0 )
222 glCopyBufferSubData( GL_ARRAY_BUFFER, GL_ELEMENT_ARRAY_BUFFER,
226 m_item->setOffset( newOffset );
231 glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, 0 );
232 glBindBuffer( GL_ARRAY_BUFFER, 0 );
246 catch(
const std::runtime_error& )
253 checkGlError(
"switching buffers during defragmentation", __FILE__, __LINE__ );
255#ifdef KICAD_GAL_PROFILE
280 wxT(
"Resizing & defragmenting container (memcpy) from %d to %d" ),
m_currentSize,
287#ifdef KICAD_GAL_PROFILE
295 glGenBuffers( 1, &newBuffer );
299#ifdef KICAD_GAL_PROFILE
301 glGetIntegerv( GL_ELEMENT_ARRAY_BUFFER_BINDING, &eaBuffer );
302 wxASSERT( eaBuffer == 0 );
305 glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, newBuffer );
306 glBufferData( GL_ELEMENT_ARRAY_BUFFER, aNewSize *
VERTEX_SIZE,
nullptr, GL_DYNAMIC_DRAW );
307 newBufferMem =
static_cast<VERTEX*
>( glMapBuffer( GL_ELEMENT_ARRAY_BUFFER, GL_WRITE_ONLY ) );
308 checkGlError(
"creating buffer during defragmentation", __FILE__, __LINE__ );
310 if( newBufferMem ==
nullptr )
312 glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, 0 );
313 glDeleteBuffers( 1, &newBuffer );
320 glUnmapBuffer( GL_ELEMENT_ARRAY_BUFFER );
321 glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, 0 );
332 catch(
const std::runtime_error& )
339 checkGlError(
"switching buffers during defragmentation", __FILE__, __LINE__ );
341#ifdef KICAD_GAL_PROFILE
366 wxT(
"Resizing & defragmenting container (RAM staged) from %d to %d" ),
373 const unsigned int usedVerts =
usedSpace();
377 std::unique_ptr<VERTEX[]> staging;
381 staging.reset(
new VERTEX[usedVerts] );
383 catch(
const std::bad_alloc& )
385 throw GPU_OOM_ERROR(
"Out of memory while staging a GPU buffer resize; "
386 "switching to software rendering." );
396 glGenBuffers( 1, &newBuffer );
397 glBindBuffer( GL_ARRAY_BUFFER, newBuffer );
398 glBufferData( GL_ARRAY_BUFFER, aNewSize *
VERTEX_SIZE,
nullptr, GL_DYNAMIC_DRAW );
399 glBindBuffer( GL_ARRAY_BUFFER, 0 );
400 checkGlError(
"allocating staged buffer during defragmentation", __FILE__, __LINE__ );
408 catch(
const std::runtime_error& )
417 checkGlError(
"switching buffers during staged defragmentation", __FILE__, __LINE__ );
434 unsigned int size = 0;
436 for(
const auto& item :
m_items )
438 size += item->GetSize();
void Map() override
Finish the vertices updates stage.
bool m_isMapped
Vertex buffer handle.
virtual unsigned int AllItemsSize() const override
bool IsMapped() const override
Prepare the container for vertices updates.
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
Flag saying whether it is safe to use glCopyBufferSubData.
unsigned int m_chunkOffset
Maximal vertex index number stored in the container.
VERTEX_ITEM * m_item
Properties of currently modified chunk & item.
FREE_CHUNK_MAP m_freeChunks
Stored VERTEX_ITEMs.
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)
ITEMS m_items
Currently modified item.
Raised when a GPU buffer allocation is predicted to exceed the available video memory.
unsigned int m_currentSize
Store the initial size, so it can be resized to this on Clear()
unsigned int m_freeSpace
Current container size, 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.