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
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 ),
89 m_totalHuge( 0 ),
90 m_totalNormal( 0 ),
91 m_indexBufSize( 0 ),
94{
95}
96
97
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
226#ifdef KICAD_GAL_PROFILE
227 wxLogTrace( traceGalProfile,
228 "Cached manager size: VBO size %u iranges %zu max elt size %u drawcalls %u",
229 cached->AllItemsSize(), m_vranges.size(), m_indexBufMaxSize, drawCalls );
230 wxLogTrace( traceGalProfile, "Timing: %s", cntDraw.to_string() );
231#endif
232
233 glBindBuffer( GL_ARRAY_BUFFER, 0 );
234 cached->ClearDirty();
235
236 // Deactivate vertex array
237 glDisableClientState( GL_COLOR_ARRAY );
238 glDisableClientState( GL_VERTEX_ARRAY );
239
240 if( m_shader != nullptr )
241 {
242 glDisableVertexAttribArray( m_shaderAttrib );
243 m_shader->Deactivate();
244 }
245
246 m_isDrawing = false;
247}
248
249
250void GPU_CACHED_MANAGER::resizeIndices( unsigned int aNewSize )
251{
252 if( aNewSize > m_indicesCapacity )
253 {
254 m_indicesCapacity = aNewSize;
255 m_indices.reset( new GLuint[m_indicesCapacity] );
256 }
257}
258
259
260// Noncached manager
265
266
268{
269 // Nothing has to be prepared
270}
271
272
274{
275 wxASSERT_MSG( false, wxT( "Not implemented yet" ) );
276}
277
278
280{
281#ifdef KICAD_GAL_PROFILE
282 PROF_TIMER totalRealTime;
283#endif /* KICAD_GAL_PROFILE */
284
285 if( m_container->GetSize() == 0 )
286 return;
287
288 VERTEX* vertices = m_container->GetAllVertices();
289 GLfloat* coordinates = (GLfloat*) ( vertices );
290 GLubyte* colors = (GLubyte*) ( vertices ) + COLOR_OFFSET;
291
293 glEnable( GL_DEPTH_TEST );
294 else
295 glDisable( GL_DEPTH_TEST );
296
297 // Prepare buffers
298 glEnableClientState( GL_VERTEX_ARRAY );
299 glEnableClientState( GL_COLOR_ARRAY );
300
301 glVertexPointer( COORD_STRIDE, GL_FLOAT, VERTEX_SIZE, coordinates );
302 glColorPointer( COLOR_STRIDE, GL_UNSIGNED_BYTE, VERTEX_SIZE, colors );
303
304 if( m_shader != nullptr ) // Use shader if applicable
305 {
306 GLfloat* shaders = (GLfloat*) ( vertices ) + SHADER_OFFSET / sizeof( GLfloat );
307
308 m_shader->Use();
309 glEnableVertexAttribArray( m_shaderAttrib );
310 glVertexAttribPointer( m_shaderAttrib, SHADER_STRIDE, GL_FLOAT, GL_FALSE, VERTEX_SIZE,
311 shaders );
312 }
313
314 glDrawArrays( GL_TRIANGLES, 0, m_container->GetSize() );
315
316#ifdef KICAD_GAL_PROFILE
317 wxLogTrace( traceGalProfile, wxT( "Noncached manager size: %d" ), m_container->GetSize() );
318#endif /* KICAD_GAL_PROFILE */
319
320 // Deactivate vertex array
321 glDisableClientState( GL_COLOR_ARRAY );
322 glDisableClientState( GL_VERTEX_ARRAY );
323
324 if( m_shader != nullptr )
325 {
326 glDisableVertexAttribArray( m_shaderAttrib );
327 m_shader->Deactivate();
328 }
329
330 m_container->Clear();
331
332#ifdef KICAD_GAL_PROFILE
333 totalRealTime.Stop();
334 wxLogTrace( traceGalProfile, wxT( "GPU_NONCACHED_MANAGER::EndDrawing(): %.1f ms" ),
335 totalRealTime.msecs() );
336#endif /* KICAD_GAL_PROFILE */
337}
338
339void GPU_MANAGER::EnableDepthTest( bool aEnabled )
340{
341 m_enableDepthTest = aEnabled;
342}
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.
std::vector< VRANGE > m_vranges
Number of huge VRANGEs (i.e. large zones) with separate draw calls.
unsigned int m_indexBufMaxSize
Size of the current VRANGE.
unsigned int m_indicesCapacity
Ranges of visible vertex indices to render.
~GPU_CACHED_MANAGER()
Prepare the stored data to be drawn.
GPU_CACHED_MANAGER(VERTEX_CONTAINER *aContainer)
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.
bool m_buffersInitialized
Pointer to the current indices buffer.
int m_totalNormal
Current size of index buffer.
boost::scoped_array< GLuint > m_indices
Current indices buffer size.
unsigned int m_indexBufSize
Maximum size taken by the index buffer for all frames rendered so far.
void resizeIndices(unsigned int aNewSize)
< Resizes the indices buffer to aNewSize if necessary
virtual void EndDrawing() override
Map vertex buffer stored in GPU memory.
GPU_MANAGER(VERTEX_CONTAINER *aContainer)
Drawing status flag.
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.
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)
SHADER * m_shader
Location of shader attributes (for glVertexAttribPointer)
Definition gpu_manager.h:92
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
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)
Display an error or warning message box with aMessage.
Definition confirm.cpp:196
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 eda_group.h:33
static constexpr size_t COLOR_OFFSET
static constexpr size_t COORD_OFFSET
static constexpr size_t VERTEX_SIZE
static constexpr size_t SHADER_OFFSET
static constexpr size_t COLOR_STRIDE
static constexpr size_t SHADER_STRIDE
static constexpr size_t COORD_STRIDE
Class to store instances of VERTEX without caching.
wxLogTrace helper definitions.
Class to handle an item held in a container.