source: trunk/nv/interface/device.hh @ 303

Last change on this file since 303 was 303, checked in by epyon, 11 years ago
  • program is now handle-based
  • all device constructs are now handle-based and do not dynamically allocate
File size: 15.2 KB
Line 
1// Copyright (C) 2012-2013 ChaosForge / Kornel Kisielewicz
2// http://chaosforge.org/
3//
4// This file is part of NV Libraries.
5// For conditions of distribution and use, see copyright notice in nv.hh
6/**
7 * @file device.hh
8 * @author Kornel Kisielewicz epyon@chaosforge.org
9 * @brief Device class
10 */
11
12#ifndef NV_DEVICE_HH
13#define NV_DEVICE_HH
14
15#include <nv/common.hh>
16#include <nv/string.hh>
17#include <nv/handle.hh>
18#include <nv/interface/uniform.hh>
19#include <nv/interface/mesh_data.hh>
20#include <nv/interface/vertex_buffer.hh>
21#include <nv/interface/image_data.hh>
22
23namespace nv
24{
25        class window;
26
27        enum texture_slot
28        {
29                TEX_DIFFUSE  = 0,
30                TEX_SPECULAR = 1,
31                TEX_NORMAL   = 2,
32                TEXTURE_0    = 0,
33                TEXTURE_1    = 1,
34                TEXTURE_2    = 2,
35                TEXTURE_3    = 3,
36                TEXTURE_4    = 4,
37                TEXTURE_5    = 5,
38                TEXTURE_6    = 6,
39                TEXTURE_7    = 7,
40        };
41
42
43        struct attribute
44        {
45                string   name;
46                int      location;
47                datatype type;
48                int      length;
49        };
50
51        typedef std::unordered_map< string, attribute >    attribute_map;
52
53        struct texture_tag {};
54        struct vertex_array_tag {};
55        struct buffer_tag {};
56        struct program_tag {};
57        typedef handle< uint32, 16, 16, buffer_tag >       buffer;
58        typedef handle< uint32, 16, 16, texture_tag >      texture;
59        typedef handle< uint32, 16, 16, vertex_array_tag > vertex_array;
60        typedef handle< uint32, 16, 16, program_tag >      program;
61
62        struct sampler
63        {
64                enum filter
65                {
66                        LINEAR,
67                        NEAREST,
68                        NEAREST_MIPMAP_NEAREST,
69                        LINEAR_MIPMAP_NEAREST,
70                        NEAREST_MIPMAP_LINEAR,
71                        LINEAR_MIPMAP_LINEAR
72                };
73                enum wrap
74                {
75                        CLAMP_TO_EDGE,
76                        CLAMP_TO_BORDER,
77                        MIRRORED_REPEAT,
78                        REPEAT
79                };
80
81                filter filter_min;
82                filter filter_max;
83                wrap wrap_s;
84                wrap wrap_t;
85
86                sampler() : filter_min( LINEAR ), filter_max( LINEAR ), wrap_s( REPEAT ), wrap_t( REPEAT ) {}
87                sampler( filter min, filter max, wrap s, wrap t )
88                        : filter_min( min ), filter_max( max ), wrap_s( s ), wrap_t( t ) {}
89                sampler( filter f, wrap w )
90                        : filter_min( f ), filter_max( f ), wrap_s( w ), wrap_t( w ) {}
91
92        };
93
94        struct buffer_info
95        {
96                buffer_type type;
97                buffer_hint hint;
98                size_t      size;
99        };
100
101
102        struct texture_info
103        {
104                ivec2        size;
105                image_format format;
106                sampler      sampler;
107        };
108
109        struct vertex_buffer_attribute
110        {
111                buffer   vbuffer;
112                datatype dtype;
113                size_t   components;
114                size_t   offset;
115                size_t   stride;
116                slot     location;
117                bool     owner;
118        };
119
120        struct vertex_array_info
121        {
122                static const int MAX_ATTRIBUTES = 24;
123
124                uint32        count;
125                buffer        index;
126                bool          index_owner;
127                datatype      index_type;
128                vertex_buffer_attribute attr[MAX_ATTRIBUTES];
129        };
130
131        struct program_info
132        {
133                attribute_map       m_attribute_map;
134                uniform_map             m_uniform_map;
135                engine_uniform_list m_engine_uniforms;
136        };
137
138        class device
139        {
140                friend class context;
141        public:
142                device()
143                {
144                        initialize_engine_uniforms();
145                }
146                virtual window* create_window( uint16 width, uint16 height, bool fullscreen ) = 0;
147                virtual window* adopt_window( void* sys_w_handle, void* sys_dc ) = 0;
148                virtual program create_program( const string& vs_source, const string& fs_source ) = 0;
149                virtual buffer create_buffer( buffer_type type, buffer_hint hint, size_t size, const void* source = nullptr ) = 0;
150                virtual image_data* create_image_data( const std::string& filename ) = 0; // temporary
151                virtual texture create_texture( ivec2 size, image_format aformat, sampler asampler, void* data = nullptr ) = 0;
152                virtual vertex_array create_vertex_array() = 0;
153                virtual void release( texture ) = 0;
154                virtual void release( buffer ) = 0;
155                virtual void release( vertex_array ) = 0;
156                virtual void release( program ) = 0;
157                virtual const texture_info* get_texture_info( texture ) const = 0;
158                virtual const buffer_info* get_buffer_info( buffer ) const = 0;
159                virtual const vertex_array_info* get_vertex_array_info( vertex_array ) const = 0;
160                virtual uint32 get_ticks() = 0;
161                virtual void delay( uint32 ms ) = 0;
162
163                virtual texture create_texture( image_data* data, sampler asampler )
164                {
165                        return create_texture( data->get_size(), data->get_format(), asampler, (void*)data->get_data() );
166                }
167
168                template < typename VTX, slot SLOT >
169                void add_vertex_buffer_impl( vertex_array, buffer, const std::false_type& )
170                {
171                }
172
173                template < typename VTX, slot SLOT >
174                void add_vertex_buffer_impl( vertex_array va, buffer vb, const std::true_type& )
175                {
176                        typedef vertex_slot_info< VTX, SLOT > vinfo;
177                        typedef datatype_traits< typename vinfo::value_type > dt_traits;
178                        add_vertex_buffer( va, SLOT, vb, type_to_enum< dt_traits::base_type >::type, dt_traits::size, vinfo::offset, sizeof( VTX ), false );
179                }
180
181                template < typename VTX, slot SLOT >
182                void add_vertex_buffer( vertex_array va, buffer vb )
183                {
184                        add_vertex_buffer_impl< VTX, SLOT >( va, vb, std::integral_constant< bool, vertex_has_slot< VTX, SLOT >::value >() );
185                }
186
187                template < typename VTX >
188                void add_vertex_buffers( vertex_array va, buffer vb )
189                {
190                        add_vertex_buffer< VTX, slot::POSITION >  ( va, vb );
191                        add_vertex_buffer< VTX, slot::TEXCOORD >  ( va, vb );
192                        add_vertex_buffer< VTX, slot::NORMAL   >  ( va, vb );
193                        add_vertex_buffer< VTX, slot::TANGENT >   ( va, vb );
194                        add_vertex_buffer< VTX, slot::BONEINDEX > ( va, vb );
195                        add_vertex_buffer< VTX, slot::BONEWEIGHT >( va, vb );
196                        add_vertex_buffer< VTX, slot::COLOR >     ( va, vb );
197                }
198
199                void add_vertex_buffers( vertex_array va, buffer buf, const mesh_raw_channel* channel )
200                {
201                        for ( uint32 s = 0; s < channel->desc.count; ++s )
202                        {
203                                const vertex_descriptor_slot& slot = channel->desc.slots[s];
204                                const datatype_info& info = get_datatype_info(slot.etype);
205                                add_vertex_buffer( va, slot.vslot, buf, info.base , info.elements, slot.offset, channel->desc.size, false );
206                        }
207                }
208
209                template < typename VTX >
210                vertex_array create_vertex_array( const VTX* v, size_t count, buffer_hint hint )
211                {
212                        // TODO: vb will not be owned or freed!
213                        vertex_array va = create_vertex_array();
214                        buffer       vb = create_buffer( VERTEX_BUFFER, hint, count * sizeof( VTX ), v );
215                        add_vertex_buffers< VTX >( va, vb );
216                        return va;
217                }
218
219                template < typename VTX >
220                vertex_array create_vertex_array( const std::vector< VTX >& data, buffer_hint hint )
221                {
222                        return create_vertex_array( data.data(), data.size(), hint );
223                }
224
225                template < typename VTX, typename IDX >
226                vertex_array create_vertex_array( const VTX* v, size_t vcount, const IDX* i, size_t icount, buffer_hint hint )
227                {
228                        vertex_array va = create_vertex_array( v, vcount, hint );
229                        buffer       ib = create_buffer( INDEX_BUFFER, hint, icount * sizeof( IDX ), i );
230                        va->set_index_buffer( ib, type_to_enum< IDX >::type, true );
231                        return va;
232                }
233
234                template < typename VTX, typename IDX >
235                vertex_array create_vertex_array( const std::vector< VTX >& data, const std::vector< IDX >& idata, buffer_hint hint )
236                {
237                        return create_vertex_array( data.data(), data.size(), idata.data(), idata.size(), hint );
238                }
239
240                void replace_vertex_buffer( vertex_array va, buffer vb, bool owner )
241                {
242                        vertex_array_info* info = get_vertex_array_info_mutable( va );
243                        if ( info )
244                        {
245                                for ( uint32 i = 0; i < info->count; ++i )
246                                {
247                                        vertex_buffer_attribute& vba = info->attr[i];
248                                        if ( vba.owner ) release( vba.vbuffer );
249                                        vba.vbuffer = vb;
250                                        vba.owner   = owner;
251                                }
252                        }
253                }
254
255                void replace_vertex_buffer( vertex_array va, buffer vb, slot location, bool owner )
256                {
257                        vertex_array_info* info = get_vertex_array_info_mutable( va );
258                        if ( info )
259                        {
260                                for ( uint32 i = 0; i < info->count; ++i )
261                                {
262                                        if ( info->attr[i].location == location )
263                                        {
264                                                vertex_buffer_attribute& vba = info->attr[i];
265                                                if ( vba.owner ) release( vba.vbuffer );
266                                                vba.vbuffer = vb;
267                                                vba.owner   = owner;
268                                        }
269                                }
270                        }
271                }
272
273                void update_attribute_offset( vertex_array va, slot location, size_t offset )
274                {
275                        vertex_array_info* info = get_vertex_array_info_mutable( va );
276                        if ( info )
277                        {
278                                for ( uint32 i = 0; i < info->count; ++i )
279                                {
280                                        if ( info->attr[i].location == location )
281                                        {
282                                                info->attr[i].offset = offset;
283                                        }
284                                }
285                        }
286                }
287
288                void set_index_buffer( vertex_array va, buffer b, datatype datatype, bool owner )
289                {
290                        vertex_array_info* info = get_vertex_array_info_mutable( va );
291                        if ( info )
292                        {
293                                if ( get_buffer_info( b )->type == INDEX_BUFFER )
294                                {
295                                        if (info->index.is_valid() && info->index_owner) release( info->index );
296
297                                        info->index       = b;
298                                        info->index_owner = owner;
299                                        info->index_type  = datatype;
300                                }
301                        }
302                }
303
304                virtual void add_vertex_buffer( vertex_array va, slot location, buffer buf, datatype datatype, size_t components, size_t offset = 0, size_t stride = 0, bool owner = true )
305                {
306                        vertex_array_info* info = get_vertex_array_info_mutable( va );
307                        if ( info )
308                        {
309                                NV_ASSERT( info->count < vertex_array_info::MAX_ATTRIBUTES, "MAX_ATTRIBUTES reached!" );
310                                vertex_buffer_attribute& p = info->attr[ info->count ];
311                                p.vbuffer    = buf;
312                                p.dtype      = datatype;
313                                p.components = components;
314                                p.offset     = offset;
315                                p.stride     = stride;
316                                p.owner      = owner;
317                                p.location   = location;
318                                info->count++;
319                        }
320                }
321
322                buffer find_buffer( vertex_array va, slot location )
323                {
324                        const vertex_array_info* info = get_vertex_array_info( va );
325                        if ( info )
326                        {
327                                for ( uint32 i = 0; i < info->count; ++i )
328                                {
329                                        if ( info->attr[i].location == location )
330                                        {
331                                                return info->attr[i].vbuffer;
332                                        }
333                                }
334                        }
335                        return buffer();
336                }
337
338                // TODO: HINTS ARE DIFFERENT!
339                vertex_array create_vertex_array( const mesh_data* data, buffer_hint hint )
340                {
341                        vertex_array  va = create_vertex_array();
342                        const std::vector< mesh_raw_channel* >& channels = data->get_raw_channels();
343                        for ( uint32 ch = 0; ch < channels.size(); ++ch )
344                        {
345                                const mesh_raw_channel* channel = channels[ch];
346                                if ( channel->count > 0 )
347                                {
348                                        buffer_type type = channel->get_buffer_type();
349                                        buffer b = create_buffer( type, hint, channel->size(), channel->data );
350                                        // TODO: no if switch
351                                        if ( type == INDEX_BUFFER )
352                                        {
353                                                set_index_buffer( va, b, channel->desc.slots[0].etype, true );
354                                        }
355                                        else
356                                        {
357                                                add_vertex_buffers( va, b, channel );
358                                        }
359                                }
360                        }
361                        return va;
362                }
363
364                int try_get_attribute_location( program p, const string& name ) const
365                {
366                        return get_attribute_location( p, name, false );
367                }
368
369                virtual int get_attribute_location( program p, const string& name, bool fatal = true ) const = 0;
370
371                template < typename T >
372                void set_uniform_array( program p, const string& name, const T* value, uint32 count, bool fatal = true )
373                {
374                        uniform_base* base = get_uniform( p, name, fatal );
375                        if ( base != nullptr )
376                        {
377                                if ( base->type_check( type_to_enum<T>::type ) )
378                                {
379                                        // TODO: nicer check
380                                        NV_ASSERT( (int)count <= base->get_length(), "LENGTH CHECK FAIL" );
381                                        ((uniform<T>*)( base ))->set_value( value, count );
382                                }
383                        }
384                }
385
386                template < typename T >
387                void set_uniform_array( const string& name, const std::vector<T>& value )
388                {
389                        set_uniform_array( program p, name, (const T*)value.data(), value.size() );
390                }
391
392                template < typename T >
393                void set_opt_uniform_array( program p, const string& name, const T* value, uint32 count )
394                {
395                        set_uniform_array( p, name, value, count, false );
396                }
397
398                template < typename T >
399                void set_opt_uniform_array( program p, const string& name, const std::vector<T>& value )
400                {
401                        set_uniform_array( p, name, (const T*)value.data(), value.size(), false );
402                }
403
404
405                template < typename T >
406                void set_uniform( program p, const string& name, const T& value, bool fatal = true )
407                {
408                        uniform_base* base = get_uniform( p, name, fatal );
409                        if ( base != nullptr )
410                        {
411                                if ( base->type_check( type_to_enum<T>::type ) )
412                                {
413                                        ((uniform<T>*)( base ))->set_value( value );
414                                }
415                        }
416                }
417
418                template < typename T >
419                void set_opt_uniform( program p, const string& name, const T& value )
420                {
421                        set_uniform( p, name, value, false );
422                }
423
424                virtual ~device()
425                {
426                        destroy_engine_uniforms();
427                }
428
429                // This is done this way to avoid compilation unit creation
430                static engine_uniform_factory_map& get_uniform_factory()
431                {
432                        static engine_uniform_factory_map s_engine_uniform_factory_map;
433                        return s_engine_uniform_factory_map;
434                }
435
436                // This is done this way to avoid compilation unit creation
437                static engine_link_uniform_factory_map& get_link_uniform_factory()
438                {
439                        static engine_link_uniform_factory_map s_engine_link_uniform_factory_map;
440                        return s_engine_link_uniform_factory_map;
441                }
442
443                virtual void prepare_program( program p ) = 0;
444
445        protected:
446                virtual uniform_base* get_uniform( program p, const string& name, bool fatal = true ) const = 0;
447
448                // TODO: remove
449                virtual vertex_array_info* get_vertex_array_info_mutable( vertex_array ) = 0;
450
451                void initialize_engine_uniforms()
452                {
453                        engine_uniform_factory_map& factory_map = get_uniform_factory();
454                        factory_map[ "nv_m_view" ]       = new engine_uniform_factory< engine_uniform_m_view >();
455                        factory_map[ "nv_m_view_inv" ]   = new engine_uniform_factory< engine_uniform_m_view_inv >();
456                        factory_map[ "nv_m_model" ]      = new engine_uniform_factory< engine_uniform_m_model >();
457                        factory_map[ "nv_m_model_inv" ]  = new engine_uniform_factory< engine_uniform_m_model_inv >();
458                        factory_map[ "nv_m_modelview" ]  = new engine_uniform_factory< engine_uniform_m_modelview >();
459                        factory_map[ "nv_m_projection" ] = new engine_uniform_factory< engine_uniform_m_projection >();
460                        factory_map[ "nv_m_normal" ]     = new engine_uniform_factory< engine_uniform_m_normal >();
461                        factory_map[ "nv_m_mvp" ]        = new engine_uniform_factory< engine_uniform_m_mvp >();
462                        factory_map[ "nv_v_camera_position" ]  = new engine_uniform_factory< engine_uniform_v_camera_position >();
463                        factory_map[ "nv_v_camera_direction" ] = new engine_uniform_factory< engine_uniform_v_camera_direction >();
464
465                        engine_link_uniform_factory_map& factory_link_map = get_link_uniform_factory();
466                        factory_link_map[ "nv_texture_0" ] = new engine_link_uniform_int<0>();
467                        factory_link_map[ "nv_texture_1" ] = new engine_link_uniform_int<1>();
468                        factory_link_map[ "nv_texture_2" ] = new engine_link_uniform_int<2>();
469                        factory_link_map[ "nv_texture_3" ] = new engine_link_uniform_int<3>();
470                        factory_link_map[ "nv_texture_4" ] = new engine_link_uniform_int<4>();
471                        factory_link_map[ "nv_texture_5" ] = new engine_link_uniform_int<5>();
472                        factory_link_map[ "nv_texture_6" ] = new engine_link_uniform_int<6>();
473                        factory_link_map[ "nv_texture_7" ] = new engine_link_uniform_int<7>();
474                        factory_link_map[ "nv_t_diffuse" ] = new engine_link_uniform_int<0>();
475                        factory_link_map[ "nv_t_specular"] = new engine_link_uniform_int<1>();
476                        factory_link_map[ "nv_t_normal"  ] = new engine_link_uniform_int<2>();
477                }
478                void destroy_engine_uniforms()
479                {
480                        for ( auto& i : get_uniform_factory() ) delete i.second;
481                        for ( auto& i : get_link_uniform_factory() ) delete i.second;
482                        get_uniform_factory().clear();
483                        get_link_uniform_factory().clear();
484                }
485
486        };
487
488} // namespace nv
489
490
491#endif // NV_DEVICE_HH
Note: See TracBrowser for help on using the repository browser.