KiCad PCB EDA Suite
Loading...
Searching...
No Matches
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 The 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 <core/profile.h>
36
37#include <typeinfo>
38#include <confirm.h>
39#include <trace_helpers.h>
40
41#ifdef KICAD_GAL_PROFILE
42#include <core/profile.h>
43#include <wx/log.h>
44#endif /* KICAD_GAL_PROFILE */
45
46using namespace KIGFX;
47
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 // Hot path: don't use wxASSERT
119 assert( m_isDrawing );
120
121 unsigned int offset = aItem->GetOffset();
122 unsigned int size = aItem->GetSize();
123
124 if( size == 0 )
125 return;
126
127 if( size <= 1000 )
128 {
129 m_totalNormal += size;
130 m_vranges.emplace_back( offset, offset + size - 1, false );
131 m_curVrangeSize += size;
132 }
133 else
134 {
135 m_totalHuge += size;
136 m_vranges.emplace_back( offset, offset + size - 1, true );
138 m_curVrangeSize = 0;
139 }
140}
141
142
144{
145 wxASSERT( m_isDrawing );
146
147 CACHED_CONTAINER* cached = static_cast<CACHED_CONTAINER*>( m_container );
148
149 if( cached->IsMapped() )
150 cached->Unmap();
151
154
156
158 glEnable( GL_DEPTH_TEST );
159 else
160 glDisable( GL_DEPTH_TEST );
161
162 // Prepare buffers
163 glEnableClientState( GL_VERTEX_ARRAY );
164 glEnableClientState( GL_COLOR_ARRAY );
165
166 // Bind vertices data buffers
167 glBindBuffer( GL_ARRAY_BUFFER, cached->GetBufferHandle() );
168 glVertexPointer( COORD_STRIDE, GL_FLOAT, VERTEX_SIZE, (GLvoid*) COORD_OFFSET );
169 glColorPointer( COLOR_STRIDE, GL_UNSIGNED_BYTE, VERTEX_SIZE, (GLvoid*) COLOR_OFFSET );
170
171 if( m_shader != nullptr ) // Use shader if applicable
172 {
173 m_shader->Use();
174 glEnableVertexAttribArray( m_shaderAttrib );
175 glVertexAttribPointer( m_shaderAttrib, SHADER_STRIDE, GL_FLOAT, GL_FALSE, VERTEX_SIZE,
176 (GLvoid*) SHADER_OFFSET );
177 }
178
179 PROF_TIMER cntDraw( "gl-draw-elements" );
180
181 int n_ranges = m_vranges.size();
182 int n = 0;
183 GLuint* iptr = m_indices.get();
184 GLuint icnt = 0;
185
186 int drawCalls = 0;
187
188 while( n < n_ranges )
189 {
190 VRANGE* cur = &m_vranges[n];
191
192 if( cur->m_isContinuous )
193 {
194 if( icnt > 0 )
195 {
196 glDrawElements( GL_TRIANGLES, icnt, GL_UNSIGNED_INT, m_indices.get() );
197 drawCalls++;
198 }
199
200 icnt = 0;
201 iptr = m_indices.get();
202
203 glDrawArrays( GL_TRIANGLES, cur->m_start, cur->m_end - cur->m_start + 1 );
204 drawCalls++;
205 }
206 else
207 {
208 for( GLuint i = cur->m_start; i <= cur->m_end; i++ )
209 {
210 *iptr++ = i;
211 icnt++;
212 }
213 }
214
215 n++;
216 }
217
218 if( icnt > 0 )
219 {
220 glDrawElements( GL_TRIANGLES, icnt, GL_UNSIGNED_INT, m_indices.get() );
221 drawCalls++;
222 }
223
224 cntDraw.Stop();
225
227 "Cached manager size: VBO size %u iranges %zu max elt size %u drawcalls %u\n",
228 cached->AllItemsSize(), m_vranges.size(), m_indexBufMaxSize, drawCalls );
229 KI_TRACE( traceGalProfile, "Timing: %s\n", cntDraw.to_string() );
230
231 glBindBuffer( GL_ARRAY_BUFFER, 0 );
232 cached->ClearDirty();
233
234 // Deactivate vertex array
235 glDisableClientState( GL_COLOR_ARRAY );
236 glDisableClientState( GL_VERTEX_ARRAY );
237
238 if( m_shader != nullptr )
239 {
240 glDisableVertexAttribArray( m_shaderAttrib );
242 }
243
244 m_isDrawing = false;
245}
246
247
248void GPU_CACHED_MANAGER::resizeIndices( unsigned int aNewSize )
249{
250 if( aNewSize > m_indicesCapacity )
251 {
252 m_indicesCapacity = aNewSize;
253 m_indices.reset( new GLuint[m_indicesCapacity] );
254 }
255}
256
257
258// Noncached manager
260 GPU_MANAGER( aContainer )
261{
262}
263
264
266{
267 // Nothing has to be prepared
268}
269
270
272{
273 wxASSERT_MSG( false, wxT( "Not implemented yet" ) );
274}
275
276
278{
279#ifdef KICAD_GAL_PROFILE
280 PROF_TIMER totalRealTime;
281#endif /* KICAD_GAL_PROFILE */
282
283 if( m_container->GetSize() == 0 )
284 return;
285
286 VERTEX* vertices = m_container->GetAllVertices();
287 GLfloat* coordinates = (GLfloat*) ( vertices );
288 GLubyte* colors = (GLubyte*) ( vertices ) + COLOR_OFFSET;
289
291 glEnable( GL_DEPTH_TEST );
292 else
293 glDisable( GL_DEPTH_TEST );
294
295 // Prepare buffers
296 glEnableClientState( GL_VERTEX_ARRAY );
297 glEnableClientState( GL_COLOR_ARRAY );
298
299 glVertexPointer( COORD_STRIDE, GL_FLOAT, VERTEX_SIZE, coordinates );
300 glColorPointer( COLOR_STRIDE, GL_UNSIGNED_BYTE, VERTEX_SIZE, colors );
301
302 if( m_shader != nullptr ) // Use shader if applicable
303 {
304 GLfloat* shaders = (GLfloat*) ( vertices ) + SHADER_OFFSET / sizeof( GLfloat );
305
306 m_shader->Use();
307 glEnableVertexAttribArray( m_shaderAttrib );
308 glVertexAttribPointer( m_shaderAttrib, SHADER_STRIDE, GL_FLOAT, GL_FALSE, VERTEX_SIZE,
309 shaders );
310 }
311
312 glDrawArrays( GL_TRIANGLES, 0, m_container->GetSize() );
313
314#ifdef KICAD_GAL_PROFILE
315 wxLogTrace( traceGalProfile, wxT( "Noncached manager size: %d" ), m_container->GetSize() );
316#endif /* KICAD_GAL_PROFILE */
317
318 // Deactivate vertex array
319 glDisableClientState( GL_COLOR_ARRAY );
320 glDisableClientState( GL_VERTEX_ARRAY );
321
322 if( m_shader != nullptr )
323 {
324 glDisableVertexAttribArray( m_shaderAttrib );
326 }
327
329
330#ifdef KICAD_GAL_PROFILE
331 totalRealTime.Stop();
332 wxLogTrace( traceGalProfile, wxT( "GPU_NONCACHED_MANAGER::EndDrawing(): %.1f ms" ),
333 totalRealTime.msecs() );
334#endif /* KICAD_GAL_PROFILE */
335}
336
337void GPU_MANAGER::EnableDepthTest( bool aEnabled )
338{
339 m_enableDepthTest = aEnabled;
340}
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:155
std::vector< VRANGE > m_vranges
Number of huge VRANGEs (i.e. large zones) with separate draw calls.
Definition: gpu_manager.h:152
unsigned int m_indexBufMaxSize
Size of the current VRANGE.
Definition: gpu_manager.h:164
unsigned int m_indicesCapacity
Ranges of visible vertex indices to render.
Definition: gpu_manager.h:149
~GPU_CACHED_MANAGER()
Prepare the stored data to be drawn.
Definition: gpu_manager.cpp:98
unsigned int m_curVrangeSize
Definition: gpu_manager.h:167
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:158
boost::scoped_array< GLuint > m_indices
Current indices buffer size.
Definition: gpu_manager.h:146
unsigned int m_indexBufSize
Maximum size taken by the index buffer for all frames rendered so far.
Definition: gpu_manager.h:161
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
static GPU_MANAGER * MakeManager(VERTEX_CONTAINER *aContainer)
Definition: gpu_manager.cpp:48
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:175
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:49
void Stop()
Save the time when this function was called, and set the counter stane to stop.
Definition: profile.h:88
std::string to_string()
Definition: profile.h:155
double msecs(bool aSinceLast=false)
Definition: profile.h:149
void DisplayError(wxWindow *aParent, const wxString &aText, int aDisplayTime)
Display an error or warning message box with aMessage.
Definition: confirm.cpp:170
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:247
static constexpr size_t COLOR_OFFSET
Definition: vertex_common.h:75
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:81
static constexpr size_t COLOR_STRIDE
Definition: vertex_common.h:78
static constexpr size_t SHADER_STRIDE
Definition: vertex_common.h:83
static constexpr size_t COORD_STRIDE
Definition: vertex_common.h:73
Class to store instances of VERTEX without caching.
wxLogTrace helper definitions.
#define KI_TRACE(aWhat,...)
Class to handle an item held in a container.