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
RevLine 
[32]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>
[301]17#include <nv/handle.hh>
[303]18#include <nv/interface/uniform.hh>
[238]19#include <nv/interface/mesh_data.hh>
[42]20#include <nv/interface/vertex_buffer.hh>
[90]21#include <nv/interface/image_data.hh>
[32]22
23namespace nv
24{
25        class window;
26
[303]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
[302]53        struct texture_tag {};
54        struct vertex_array_tag {};
55        struct buffer_tag {};
[303]56        struct program_tag {};
[302]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;
[303]60        typedef handle< uint32, 16, 16, program_tag >      program;
[302]61
[301]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
[302]94        struct buffer_info
95        {
96                buffer_type type;
97                buffer_hint hint;
98                size_t      size;
99        };
100
101
[301]102        struct texture_info
103        {
104                ivec2        size;
105                image_format format;
106                sampler      sampler;
107        };
108
[302]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        };
[301]119
[302]120        struct vertex_array_info
121        {
122                static const int MAX_ATTRIBUTES = 24;
[301]123
[302]124                uint32        count;
125                buffer        index;
126                bool          index_owner;
127                datatype      index_type;
128                vertex_buffer_attribute attr[MAX_ATTRIBUTES];
129        };
130
[303]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
[32]138        class device
139        {
[302]140                friend class context;
[32]141        public:
[303]142                device()
143                {
144                        initialize_engine_uniforms();
145                }
[228]146                virtual window* create_window( uint16 width, uint16 height, bool fullscreen ) = 0;
[245]147                virtual window* adopt_window( void* sys_w_handle, void* sys_dc ) = 0;
[303]148                virtual program create_program( const string& vs_source, const string& fs_source ) = 0;
[302]149                virtual buffer create_buffer( buffer_type type, buffer_hint hint, size_t size, const void* source = nullptr ) = 0;
[90]150                virtual image_data* create_image_data( const std::string& filename ) = 0; // temporary
[301]151                virtual texture create_texture( ivec2 size, image_format aformat, sampler asampler, void* data = nullptr ) = 0;
[303]152                virtual vertex_array create_vertex_array() = 0;
[302]153                virtual void release( texture ) = 0;
154                virtual void release( buffer ) = 0;
[303]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;
[92]160                virtual uint32 get_ticks() = 0;
161                virtual void delay( uint32 ms ) = 0;
[303]162
[301]163                virtual texture create_texture( image_data* data, sampler asampler )
[292]164                {
[301]165                        return create_texture( data->get_size(), data->get_format(), asampler, (void*)data->get_data() );
[292]166                }
167
[237]168                template < typename VTX, slot SLOT >
[302]169                void add_vertex_buffer_impl( vertex_array, buffer, const std::false_type& )
[237]170                {
171                }
172
173                template < typename VTX, slot SLOT >
[302]174                void add_vertex_buffer_impl( vertex_array va, buffer vb, const std::true_type& )
[237]175                {
176                        typedef vertex_slot_info< VTX, SLOT > vinfo;
177                        typedef datatype_traits< typename vinfo::value_type > dt_traits;
[302]178                        add_vertex_buffer( va, SLOT, vb, type_to_enum< dt_traits::base_type >::type, dt_traits::size, vinfo::offset, sizeof( VTX ), false );
[237]179                }
180
181                template < typename VTX, slot SLOT >
[302]182                void add_vertex_buffer( vertex_array va, buffer vb )
[237]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 >
[302]188                void add_vertex_buffers( vertex_array va, buffer vb )
[237]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 );
[302]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 );
[237]216                        return va;
217                }
218
219                template < typename VTX >
[302]220                vertex_array create_vertex_array( const std::vector< VTX >& data, buffer_hint hint )
[237]221                {
222                        return create_vertex_array( data.data(), data.size(), hint );
223                }
224
225                template < typename VTX, typename IDX >
[302]226                vertex_array create_vertex_array( const VTX* v, size_t vcount, const IDX* i, size_t icount, buffer_hint hint )
[237]227                {
[302]228                        vertex_array va = create_vertex_array( v, vcount, hint );
229                        buffer       ib = create_buffer( INDEX_BUFFER, hint, icount * sizeof( IDX ), i );
[237]230                        va->set_index_buffer( ib, type_to_enum< IDX >::type, true );
231                        return va;
232                }
233
234                template < typename VTX, typename IDX >
[302]235                vertex_array create_vertex_array( const std::vector< VTX >& data, const std::vector< IDX >& idata, buffer_hint hint )
[237]236                {
237                        return create_vertex_array( data.data(), data.size(), idata.data(), idata.size(), hint );
238                }
239
[302]240                void replace_vertex_buffer( vertex_array va, buffer vb, bool owner )
241                {
[303]242                        vertex_array_info* info = get_vertex_array_info_mutable( va );
[302]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                {
[303]257                        vertex_array_info* info = get_vertex_array_info_mutable( va );
[302]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                {
[303]275                        vertex_array_info* info = get_vertex_array_info_mutable( va );
[302]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                {
[303]290                        vertex_array_info* info = get_vertex_array_info_mutable( va );
[302]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
[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 )
[302]305                {
[303]306                        vertex_array_info* info = get_vertex_array_info_mutable( va );
[302]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                {
[303]324                        const vertex_array_info* info = get_vertex_array_info( va );
[302]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
[238]338                // TODO: HINTS ARE DIFFERENT!
[302]339                vertex_array create_vertex_array( const mesh_data* data, buffer_hint hint )
[238]340                {
[302]341                        vertex_array  va = create_vertex_array();
[280]342                        const std::vector< mesh_raw_channel* >& channels = data->get_raw_channels();
343                        for ( uint32 ch = 0; ch < channels.size(); ++ch )
[238]344                        {
[280]345                                const mesh_raw_channel* channel = channels[ch];
[287]346                                if ( channel->count > 0 )
[280]347                                {
[302]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 )
[287]352                                        {
[302]353                                                set_index_buffer( va, b, channel->desc.slots[0].etype, true );
[287]354                                        }
355                                        else
356                                        {
[302]357                                                add_vertex_buffers( va, b, channel );
[287]358                                        }
[280]359                                }
[238]360                        }
361                        return va;
362                }
363
[303]364                int try_get_attribute_location( program p, const string& name ) const
365                {
366                        return get_attribute_location( p, name, false );
367                }
[238]368
[303]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
[302]424                virtual ~device()
425                {
[303]426                        destroy_engine_uniforms();
[302]427                }
[303]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
[302]445        protected:
[303]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
[32]486        };
487
488} // namespace nv
489
490
491#endif // NV_DEVICE_HH
Note: See TracBrowser for help on using the repository browser.