]> git.tdb.fi Git - libs/gl.git/blob - source/core/uniformblock.cpp
Check the flat qualifier from the correct member
[libs/gl.git] / source / core / uniformblock.cpp
1 #include <algorithm>
2 #include "device.h"
3 #include "uniformblock.h"
4
5 using namespace std;
6
7 namespace Msp {
8 namespace GL {
9
10 UniformBlock::UniformBlock(const ReflectData::UniformBlockInfo &info):
11         UniformBlockBackend(info.bind_point>=0),
12         data(info.data_size)
13 { }
14
15 size_t UniformBlock::get_alignment() const
16 {
17         return Device::get_current().get_info().limits.uniform_buffer_alignment;
18 }
19
20 void UniformBlock::store(const ReflectData::UniformInfo &info, size_t array_size, const void *value)
21 {
22         array_size = min(array_size, max<size_t>(info.array_size, 1U));
23
24         size_t store_offset;
25         bool packed;
26         if(info.block->bind_point==ReflectData::DEFAULT_BLOCK)
27         {
28                 if(info.location<0)
29                         return;
30
31                 store_offset = info.location*16;
32                 packed = true;
33         }
34         else
35         {
36                 store_offset = info.offset;
37                 if(array_size!=1 && info.array_stride!=get_type_size(info.type))
38                         packed = false;
39                 else if(is_matrix(info.type))
40                         packed = (info.matrix_stride==get_type_size(get_matrix_column_type(info.type)));
41                 else
42                         packed = true;
43         }
44
45         char *store_ptr = data.data()+store_offset;
46         const char *value_ptr = static_cast<const char *>(value);
47         if(packed)
48         {
49                 size_t value_size = array_size*get_type_size(info.type);
50                 check_store_range(store_offset, value_size);
51                 copy(value_ptr, value_ptr+value_size, store_ptr);
52         }
53         else if(is_matrix(info.type))
54         {
55                 unsigned col_size = get_type_size(get_matrix_column_type(info.type));
56                 unsigned cols = get_type_size(info.type)/col_size;
57                 check_store_range(store_offset, (array_size-1)*info.array_stride+(cols-1)*info.matrix_stride+col_size);
58                 for(unsigned i=0; i<array_size; ++i)
59                 {
60                         char *elem_ptr = store_ptr;
61                         for(unsigned j=0; j<cols; ++j)
62                         {
63                                 copy(value_ptr, value_ptr+col_size, elem_ptr);
64                                 value_ptr += col_size;
65                                 elem_ptr += info.matrix_stride;
66                         }
67                         store_ptr += info.array_stride;
68                 }
69         }
70         else
71         {
72                 unsigned elem_size = get_type_size(info.type);
73                 check_store_range(store_offset, (array_size-1)*info.array_stride+elem_size);
74                 for(unsigned i=0; i<array_size; ++i)
75                 {
76                         copy(value_ptr, value_ptr+elem_size, store_ptr);
77                         value_ptr += elem_size;
78                         store_ptr += info.array_stride;
79                 }
80         }
81
82         mark_dirty();
83 }
84
85 void UniformBlock::check_store_range(size_t offs, size_t size)
86 {
87 #ifdef DEBUG
88         if(offs>data.size() || offs+size>data.size())
89                 throw out_of_range("UniformBlock::store");
90 #endif
91 }
92
93 } // namespace GL
94 } // namespace Msp