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 (void) drawCalls; // silence warning
225 cntDraw.Stop();
226
227#ifdef KICAD_GAL_PROFILE
228 wxLogTrace( traceGalProfile,
229 "Cached manager size: VBO size %u iranges %zu max elt size %u drawcalls %u",
230 cached->AllItemsSize(), m_vranges.size(), m_indexBufMaxSize, drawCalls );
231 wxLogTrace( traceGalProfile, "Timing: %s", cntDraw.to_string() );
232#endif
233
234 glBindBuffer( GL_ARRAY_BUFFER, 0 );
235 cached->ClearDirty();
236
237 // Deactivate vertex array
238 glDisableClientState( GL_COLOR_ARRAY );
239 glDisableClientState( GL_VERTEX_ARRAY );
240
241 if( m_shader != nullptr )
242 {
243 glDisableVertexAttribArray( m_shaderAttrib );
244 m_shader->Deactivate();
245 }
246
247 m_isDrawing = false;
248}
249
250
251void GPU_CACHED_MANAGER::resizeIndices( unsigned int aNewSize )
252{
253 if( aNewSize > m_indicesCapacity )
254 {
255 m_indicesCapacity = aNewSize;
256 m_indices.reset( new GLuint[m_indicesCapacity] );
257 }
258}
259
260
261// Noncached manager
266
267
269{
270 // Nothing has to be prepared
271}
272
273
275{
276 wxASSERT_MSG( false, wxT( "Not implemented yet" ) );
277}
278
279
281{
282#ifdef KICAD_GAL_PROFILE
283 PROF_TIMER totalRealTime;
284#endif /* KICAD_GAL_PROFILE */
285
286 if( m_container->GetSize() == 0 )
287 return;
288
289 VERTEX* vertices = m_container->GetAllVertices();
290 GLfloat* coordinates = (GLfloat*) ( vertices );
291 GLubyte* colors = (GLubyte*) ( vertices ) + COLOR_OFFSET;
292
294 glEnable( GL_DEPTH_TEST );
295 else
296 glDisable( GL_DEPTH_TEST );
297
298 // Prepare buffers
299 glEnableClientState( GL_VERTEX_ARRAY );
300 glEnableClientState( GL_COLOR_ARRAY );
301
302 glVertexPointer( COORD_STRIDE, GL_FLOAT, VERTEX_SIZE, coordinates );
303 glColorPointer( COLOR_STRIDE, GL_UNSIGNED_BYTE, VERTEX_SIZE, colors );
304
305 if( m_shader != nullptr ) // Use shader if applicable
306 {
307 GLfloat* shaders = (GLfloat*) ( vertices ) + SHADER_OFFSET / sizeof( GLfloat );
308
309 m_shader->Use();
310 glEnableVertexAttribArray( m_shaderAttrib );
311 glVertexAttribPointer( m_shaderAttrib, SHADER_STRIDE, GL_FLOAT, GL_FALSE, VERTEX_SIZE,
312 shaders );
313 }
314
315 glDrawArrays( GL_TRIANGLES, 0, m_container->GetSize() );
316
317#ifdef KICAD_GAL_PROFILE
318 wxLogTrace( traceGalProfile, wxT( "Noncached manager size: %d" ), m_container->GetSize() );
319#endif /* KICAD_GAL_PROFILE */
320
321 // Deactivate vertex array
322 glDisableClientState( GL_COLOR_ARRAY );
323 glDisableClientState( GL_VERTEX_ARRAY );
324
325 if( m_shader != nullptr )
326 {
327 glDisableVertexAttribArray( m_shaderAttrib );
328 m_shader->Deactivate();
329 }
330
331 m_container->Clear();
332
333#ifdef KICAD_GAL_PROFILE
334 totalRealTime.Stop();
335 wxLogTrace( traceGalProfile, wxT( "GPU_NONCACHED_MANAGER::EndDrawing(): %.1f ms" ),
336 totalRealTime.msecs() );
337#endif /* KICAD_GAL_PROFILE */
338}
339
340void GPU_MANAGER::EnableDepthTest( bool aEnabled )
341{
342 m_enableDepthTest = aEnabled;
343}
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:50
void Stop()
Save the time when this function was called, and set the counter stane to stop.
Definition profile.h:90
std::string to_string()
Definition profile.h:157
double msecs(bool aSinceLast=false)
Definition profile.h:151
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.