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 (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 <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 n++;
215 }
216
217 if( icnt > 0 )
218 {
219 glDrawElements( GL_TRIANGLES, icnt, GL_UNSIGNED_INT, m_indices.get() );
220 drawCalls++;
221 }
222
223 cntDraw.Stop();
224
226 "Cached manager size: VBO size %u iranges %zu max elt size %u drawcalls %u\n",
227 cached->AllItemsSize(), m_vranges.size(), m_indexBufMaxSize, drawCalls );
228 KI_TRACE( traceGalProfile, "Timing: %s\n", cntDraw.to_string() );
229
230 glBindBuffer( GL_ARRAY_BUFFER, 0 );
231 cached->ClearDirty();
232
233 // Deactivate vertex array
234 glDisableClientState( GL_COLOR_ARRAY );
235 glDisableClientState( GL_VERTEX_ARRAY );
236
237 if( m_shader != nullptr )
238 {
239 glDisableVertexAttribArray( m_shaderAttrib );
241 }
242
243 m_isDrawing = false;
244}
245
246
247void GPU_CACHED_MANAGER::resizeIndices( unsigned int aNewSize )
248{
249 if( aNewSize > m_indicesCapacity )
250 {
251 m_indicesCapacity = aNewSize;
252 m_indices.reset( new GLuint[m_indicesCapacity] );
253 }
254}
255
256
257// Noncached manager
259 GPU_MANAGER( aContainer )
260{
261}
262
263
265{
266 // Nothing has to be prepared
267}
268
269
271{
272 wxASSERT_MSG( false, wxT( "Not implemented yet" ) );
273}
274
275
277{
278#ifdef KICAD_GAL_PROFILE
279 PROF_TIMER totalRealTime;
280#endif /* KICAD_GAL_PROFILE */
281
282 if( m_container->GetSize() == 0 )
283 return;
284
285 VERTEX* vertices = m_container->GetAllVertices();
286 GLfloat* coordinates = (GLfloat*) ( vertices );
287 GLubyte* colors = (GLubyte*) ( vertices ) + COLOR_OFFSET;
288
290 glEnable( GL_DEPTH_TEST );
291 else
292 glDisable( GL_DEPTH_TEST );
293
294 // Prepare buffers
295 glEnableClientState( GL_VERTEX_ARRAY );
296 glEnableClientState( GL_COLOR_ARRAY );
297
298 glVertexPointer( COORD_STRIDE, GL_FLOAT, VERTEX_SIZE, coordinates );
299 glColorPointer( COLOR_STRIDE, GL_UNSIGNED_BYTE, VERTEX_SIZE, colors );
300
301 if( m_shader != nullptr ) // Use shader if applicable
302 {
303 GLfloat* shaders = (GLfloat*) ( vertices ) + SHADER_OFFSET / sizeof( GLfloat );
304
305 m_shader->Use();
306 glEnableVertexAttribArray( m_shaderAttrib );
307 glVertexAttribPointer( m_shaderAttrib, SHADER_STRIDE, GL_FLOAT, GL_FALSE, VERTEX_SIZE,
308 shaders );
309 }
310
311 glDrawArrays( GL_TRIANGLES, 0, m_container->GetSize() );
312
313#ifdef KICAD_GAL_PROFILE
314 wxLogTrace( traceGalProfile, wxT( "Noncached manager size: %d" ), m_container->GetSize() );
315#endif /* KICAD_GAL_PROFILE */
316
317 // Deactivate vertex array
318 glDisableClientState( GL_COLOR_ARRAY );
319 glDisableClientState( GL_VERTEX_ARRAY );
320
321 if( m_shader != nullptr )
322 {
323 glDisableVertexAttribArray( m_shaderAttrib );
325 }
326
328
329#ifdef KICAD_GAL_PROFILE
330 totalRealTime.Stop();
331 wxLogTrace( traceGalProfile, wxT( "GPU_NONCACHED_MANAGER::EndDrawing(): %.1f ms" ),
332 totalRealTime.msecs() );
333#endif /* KICAD_GAL_PROFILE */
334}
335
336void GPU_MANAGER::EnableDepthTest( bool aEnabled )
337{
338 m_enableDepthTest = aEnabled;
339}
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
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: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: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: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.