KiCad PCB EDA Suite
gpu_manager.cpp
Go to the documentation of this file.
1/*
2 * This program source code file is part of KiCad, a free EDA CAD application.
3 *
4 * Copyright 2013-2017 CERN
5 * Copyright (C) 2021 KiCad Developers, see AUTHORS.txt for contributors.
6 *
7 * @author Maciej Suminski <[email protected]>
8 *
9 * This program is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU General Public License
11 * as published by the Free Software Foundation; either version 2
12 * of the License, or (at your option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, you may find one here:
21 * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
22 * or you may search the http://www.gnu.org website for the version 2 license,
23 * or you may write to the Free Software Foundation, Inc.,
24 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
25 */
26
31#include <gal/opengl/shader.h>
32#include <gal/opengl/utils.h>
34
35#include <profile.h>
36
37#include <typeinfo>
38#include <confirm.h>
39#include <trace_helpers.h>
40
41#ifdef KICAD_GAL_PROFILE
42#include <profile.h>
43#include <wx/log.h>
44#endif /* KICAD_GAL_PROFILE */
45
46using namespace KIGFX;
47
48GPU_MANAGER* GPU_MANAGER::MakeManager( VERTEX_CONTAINER* aContainer )
49{
50 if( aContainer->IsCached() )
51 return new GPU_CACHED_MANAGER( aContainer );
52 else
53 return new GPU_NONCACHED_MANAGER( aContainer );
54}
55
56
58 m_isDrawing( false ),
59 m_container( aContainer ),
60 m_shader( nullptr ),
61 m_shaderAttrib( 0 ),
62 m_enableDepthTest( true )
63{
64}
65
66
68{
69}
70
71
73{
74 m_shader = &aShader;
75 m_shaderAttrib = m_shader->GetAttribute( "a_shaderParams" );
76
77 if( m_shaderAttrib == -1 )
78 {
79 DisplayError( nullptr, wxT( "Could not get the shader attribute location" ) );
80 }
81}
82
83
84// Cached manager
86 GPU_MANAGER( aContainer ),
87 m_buffersInitialized( false ),
88 m_indicesCapacity( 0 ),
89 m_totalHuge( 0 ),
90 m_totalNormal( 0 ),
91 m_indexBufSize( 0 ),
92 m_indexBufMaxSize( 0 ),
93 m_curVrangeSize( 0 )
94{
95}
96
97
99{
100}
101
102
104{
105 wxASSERT( !m_isDrawing );
106
107 m_curVrangeSize = 0;
109 m_indexBufSize = 0;
110 m_vranges.clear();
111
112 m_isDrawing = true;
113}
114
115
117{
118 wxASSERT( m_isDrawing );
119
120 unsigned int offset = aItem->GetOffset();
121 unsigned int size = aItem->GetSize();
122
123 if( size > 1000 )
124 {
125 m_totalHuge += size;
126 m_vranges.emplace_back( offset, offset + size - 1, true );
128 m_curVrangeSize = 0;
129 }
130 else if ( size > 0 )
131 {
132 m_totalNormal += size;
133 m_vranges.emplace_back( offset, offset + size - 1, false );
134 m_curVrangeSize += size;
135 }
136}
137
138
140{
141 wxASSERT( m_isDrawing );
142
143 CACHED_CONTAINER* cached = static_cast<CACHED_CONTAINER*>( m_container );
144
145 if( cached->IsMapped() )
146 cached->Unmap();
147
150
152
154 glEnable( GL_DEPTH_TEST );
155 else
156 glDisable( GL_DEPTH_TEST );
157
158 // Prepare buffers
159 glEnableClientState( GL_VERTEX_ARRAY );
160 glEnableClientState( GL_COLOR_ARRAY );
161
162 // Bind vertices data buffers
163 glBindBuffer( GL_ARRAY_BUFFER, cached->GetBufferHandle() );
164 glVertexPointer( COORD_STRIDE, GL_FLOAT, VERTEX_SIZE, (GLvoid*) COORD_OFFSET );
165 glColorPointer( COLOR_STRIDE, GL_UNSIGNED_BYTE, VERTEX_SIZE, (GLvoid*) COLOR_OFFSET );
166
167 if( m_shader != nullptr ) // Use shader if applicable
168 {
169 m_shader->Use();
170 glEnableVertexAttribArray( m_shaderAttrib );
171 glVertexAttribPointer( m_shaderAttrib, SHADER_STRIDE, GL_FLOAT, GL_FALSE, VERTEX_SIZE,
172 (GLvoid*) SHADER_OFFSET );
173 }
174
175 PROF_TIMER cntDraw( "gl-draw-elements" );
176
177 int n_ranges = m_vranges.size();
178 int n = 0;
179 GLuint* iptr = m_indices.get();
180 GLuint icnt = 0;
181
182 int drawCalls = 0;
183
184 while( n < n_ranges )
185 {
186 VRANGE* cur = &m_vranges[n];
187
188 if( cur->m_isContinuous )
189 {
190 if( icnt > 0 )
191 {
192 glDrawElements( GL_TRIANGLES, icnt, GL_UNSIGNED_INT, m_indices.get() );
193 drawCalls++;
194 }
195
196 icnt = 0;
197 iptr = m_indices.get();
198
199 glDrawArrays( GL_TRIANGLES, cur->m_start, cur->m_end - cur->m_start + 1 );
200 drawCalls++;
201 }
202 else
203 {
204 for( GLuint i = cur->m_start; i <= cur->m_end; i++ )
205 {
206 *iptr++ = i;
207 icnt++;
208 }
209 }
210 n++;
211 }
212
213 if( icnt > 0 )
214 {
215 glDrawElements( GL_TRIANGLES, icnt, GL_UNSIGNED_INT, m_indices.get() );
216 drawCalls++;
217 }
218
219 cntDraw.Stop();
220
222 "Cached manager size: VBO size %u iranges %zu max elt size %u drawcalls %u\n",
223 cached->AllItemsSize(), m_vranges.size(), m_indexBufMaxSize, drawCalls );
224 KI_TRACE( traceGalProfile, "Timing: %s\n", cntDraw.to_string() );
225
226 glBindBuffer( GL_ARRAY_BUFFER, 0 );
227 cached->ClearDirty();
228
229 // Deactivate vertex array
230 glDisableClientState( GL_COLOR_ARRAY );
231 glDisableClientState( GL_VERTEX_ARRAY );
232
233 if( m_shader != nullptr )
234 {
235 glDisableVertexAttribArray( m_shaderAttrib );
237 }
238
239 m_isDrawing = false;
240}
241
242
243void GPU_CACHED_MANAGER::resizeIndices( unsigned int aNewSize )
244{
245 if( aNewSize > m_indicesCapacity )
246 {
247 m_indicesCapacity = aNewSize;
248 m_indices.reset( new GLuint[m_indicesCapacity] );
249 }
250}
251
252
253// Noncached manager
255 GPU_MANAGER( aContainer )
256{
257}
258
259
261{
262 // Nothing has to be prepared
263}
264
265
267{
268 wxASSERT_MSG( false, wxT( "Not implemented yet" ) );
269}
270
271
273{
274#ifdef KICAD_GAL_PROFILE
275 PROF_TIMER totalRealTime;
276#endif /* KICAD_GAL_PROFILE */
277
278 if( m_container->GetSize() == 0 )
279 return;
280
281 VERTEX* vertices = m_container->GetAllVertices();
282 GLfloat* coordinates = (GLfloat*) ( vertices );
283 GLubyte* colors = (GLubyte*) ( vertices ) + COLOR_OFFSET;
284
286 glEnable( GL_DEPTH_TEST );
287 else
288 glDisable( GL_DEPTH_TEST );
289
290 // Prepare buffers
291 glEnableClientState( GL_VERTEX_ARRAY );
292 glEnableClientState( GL_COLOR_ARRAY );
293
294 glVertexPointer( COORD_STRIDE, GL_FLOAT, VERTEX_SIZE, coordinates );
295 glColorPointer( COLOR_STRIDE, GL_UNSIGNED_BYTE, VERTEX_SIZE, colors );
296
297 if( m_shader != nullptr ) // Use shader if applicable
298 {
299 GLfloat* shaders = (GLfloat*) ( vertices ) + SHADER_OFFSET / sizeof( GLfloat );
300
301 m_shader->Use();
302 glEnableVertexAttribArray( m_shaderAttrib );
303 glVertexAttribPointer( m_shaderAttrib, SHADER_STRIDE, GL_FLOAT, GL_FALSE, VERTEX_SIZE,
304 shaders );
305 }
306
307 glDrawArrays( GL_TRIANGLES, 0, m_container->GetSize() );
308
309#ifdef KICAD_GAL_PROFILE
310 wxLogTrace( traceGalProfile, wxT( "Noncached manager size: %d" ), m_container->GetSize() );
311#endif /* KICAD_GAL_PROFILE */
312
313 // Deactivate vertex array
314 glDisableClientState( GL_COLOR_ARRAY );
315 glDisableClientState( GL_VERTEX_ARRAY );
316
317 if( m_shader != nullptr )
318 {
319 glDisableVertexAttribArray( m_shaderAttrib );
321 }
322
324
325#ifdef KICAD_GAL_PROFILE
326 totalRealTime.Stop();
327 wxLogTrace( traceGalProfile, wxT( "GPU_NONCACHED_MANAGER::EndDrawing(): %.1f ms" ),
328 totalRealTime.msecs() );
329#endif /* KICAD_GAL_PROFILE */
330}
331
332void GPU_MANAGER::EnableDepthTest( bool aEnabled )
333{
334 m_enableDepthTest = aEnabled;
335}
Class to store VERTEX instances with caching.
virtual unsigned int GetBufferHandle() const =0
Return handle to the vertex buffer.
virtual unsigned int AllItemsSize() const
virtual bool IsMapped() const =0
Return true if vertex buffer is currently mapped.
virtual void Unmap() override=0
Finish the vertices updates stage.
int m_totalHuge
Number of regular VRANGEs (small items) pooled into single draw call.
Definition: gpu_manager.h:153
std::vector< VRANGE > m_vranges
Number of huge VRANGEs (i.e. large zones) with separate draw calls.
Definition: gpu_manager.h:150
unsigned int m_indexBufMaxSize
Size of the current VRANGE.
Definition: gpu_manager.h:162
unsigned int m_indicesCapacity
Ranges of visible vertex indices to render.
Definition: gpu_manager.h:147
~GPU_CACHED_MANAGER()
Prepare the stored data to be drawn.
Definition: gpu_manager.cpp:98
unsigned int m_curVrangeSize
Definition: gpu_manager.h:165
GPU_CACHED_MANAGER(VERTEX_CONTAINER *aContainer)
Definition: gpu_manager.cpp:85
virtual void DrawIndices(const VERTEX_ITEM *aItem) override
Clear the container after drawing routines.
virtual void BeginDrawing() override
Make the GPU draw given range of vertices.
int m_totalNormal
Current size of index buffer.
Definition: gpu_manager.h:156
boost::scoped_array< GLuint > m_indices
Current indices buffer size.
Definition: gpu_manager.h:144
unsigned int m_indexBufSize
Maximum size taken by the index buffer for all frames rendered so far.
Definition: gpu_manager.h:159
void resizeIndices(unsigned int aNewSize)
< Resizes the indices buffer to aNewSize if necessary
virtual void EndDrawing() override
Map vertex buffer stored in GPU memory.
Class to handle uploading vertices and indices to GPU in drawing purposes.
Definition: gpu_manager.h:46
GPU_MANAGER(VERTEX_CONTAINER *aContainer)
Drawing status flag.
Definition: gpu_manager.cpp:57
int m_shaderAttrib
true: enable Z test when drawing
Definition: gpu_manager.h:95
virtual void SetShader(SHADER &aShader)
Allow using shaders with the stored data.
Definition: gpu_manager.cpp:72
void EnableDepthTest(bool aEnabled)
Enable/disable Z buffer depth test.
VERTEX_CONTAINER * m_container
Shader handling.
Definition: gpu_manager.h:89
bool m_isDrawing
Container that stores vertices data.
Definition: gpu_manager.h:86
SHADER * m_shader
Location of shader attributes (for glVertexAttribPointer)
Definition: gpu_manager.h:92
virtual ~GPU_MANAGER()
Definition: gpu_manager.cpp:67
virtual void BeginDrawing() override
Make the GPU draw given range of vertices.
GPU_NONCACHED_MANAGER(VERTEX_CONTAINER *aContainer)
Prepare the stored data to be drawn.
virtual void EndDrawing() override
Clear the container after drawing routines.
virtual void DrawIndices(const VERTEX_ITEM *aItem) override
Clear the container after drawing routines.
Provide the access to the OpenGL shaders.
Definition: shader.h:77
void Use()
Use the shader.
Definition: shader.h:126
int GetAttribute(const std::string &aAttributeName) const
Get an attribute location.
Definition: shader.cpp:172
void Deactivate()
Deactivate the shader and use the default OpenGL program.
Definition: shader.h:135
virtual unsigned int GetSize() const
Return amount of vertices currently stored in the container.
virtual void Clear()=0
Remove all data stored in the container and restores its original state.
VERTEX * GetAllVertices() const
Return pointer to the vertices stored in the container.
virtual bool IsCached() const =0
Return true if the container caches vertex data in RAM or video memory.
void ClearDirty()
Clear the dirty flag to prevent reuploading vertices to the GPU memory.
unsigned int GetOffset() const
Return data offset in the container.
Definition: vertex_item.h:68
unsigned int GetSize() const
Return information about number of vertices stored.
Definition: vertex_item.h:58
A small class to help profiling.
Definition: profile.h:47
void Stop()
Save the time when this function was called, and set the counter stane to stop.
Definition: profile.h:86
std::string to_string()
Definition: profile.h:153
double msecs(bool aSinceLast=false)
Definition: profile.h:147
void DisplayError(wxWindow *aParent, const wxString &aText, int aDisplayTime)
Display an error or warning message box with aMessage.
Definition: confirm.cpp:280
This file is part of the common library.
const wxChar *const traceGalProfile
Flag to enable debug output of GAL performance profiling.
The Cairo implementation of the graphics abstraction layer.
Definition: color4d.cpp:266
static constexpr size_t COLOR_OFFSET
Definition: vertex_common.h:74
static constexpr size_t COORD_OFFSET
Definition: vertex_common.h:70
static constexpr size_t VERTEX_SIZE
Definition: vertex_common.h:67
static constexpr size_t SHADER_OFFSET
Definition: vertex_common.h:79
static constexpr size_t COLOR_STRIDE
Definition: vertex_common.h:76
static constexpr size_t SHADER_STRIDE
Definition: vertex_common.h:81
static constexpr size_t COORD_STRIDE
Definition: vertex_common.h:72
Class to store instances of VERTEX without caching.
wxLogTrace helper definitions.
#define KI_TRACE(aWhat,...)
Class to handle an item held in a container.