]> git.tdb.fi Git - libs/gl.git/blob - source/core/buffer.h
Check the flat qualifier from the correct member
[libs/gl.git] / source / core / buffer.h
1 #ifndef MSP_GL_BUFFER_H_
2 #define MSP_GL_BUFFER_H_
3
4 #include <stdexcept>
5 #include <string>
6 #include "buffer_backend.h"
7
8 namespace Msp {
9 namespace GL {
10
11 class buffer_too_small: public std::logic_error
12 {
13 public:
14         buffer_too_small(const std::string &w): std::logic_error(w) { }
15         virtual ~buffer_too_small() throw() { }
16 };
17
18 enum BufferUsage
19 {
20         STATIC,
21         STREAMING
22 };
23
24 /**
25 Stores data in GPU memory.
26
27 Memory must be allocated for the buffer by calling storage().  Contents can
28 then be modified either synchronously with the data() and sub_data() functions,
29 or asynchronously by memory-mapping the buffer.
30
31 Buffers can have a static or streaming usage pattern.  Streaming buffers can be
32 memory mapped for less update overhead, but memory space is more limited.  If
33 the buffer is updated only rarely, static is recommended.
34
35 Applications normally don't need to deal with Buffers directly.  They're
36 managed by other classes such as Mesh and ProgramData.
37 */
38 class Buffer: public BufferBackend
39 {
40         friend BufferBackend;
41
42 public:
43         /**
44         An RAII handle for asynchronously writing data into a buffer.
45         */
46         class AsyncTransfer: public NonCopyable
47         {
48                 friend BufferBackend;
49                 friend class Buffer;
50
51         private:
52                 Buffer *buffer = 0;
53                 std::size_t offset = 0;
54                 std::size_t size = 0;
55                 void *dest_addr = 0;
56
57                 AsyncTransfer(Buffer &, std::size_t, std::size_t);
58         public:
59                 AsyncTransfer() = default;
60                 AsyncTransfer(AsyncTransfer &&);
61                 AsyncTransfer &operator=(AsyncTransfer &&);
62                 ~AsyncTransfer();
63
64         private:
65                 void allocate();
66                 void finalize();
67
68         public:
69                 /** Returns an address for writing the data.  It should not be used
70                 beyond the lifetime of the object. */
71                 void *get_address() { return dest_addr; }
72         };
73
74 private:
75         std::size_t size = 0;
76         BufferUsage usage = STATIC;
77         bool mapped = false;
78
79 public:
80         /** Sets storage size and usage pattern and allocates memory for the buffer.
81         Size and usage cannot be changed once set. */
82         void storage(std::size_t, BufferUsage);
83
84         /** Replaces contents of the entire buffer.  Allocated storage must exist.
85         The data must have size matching the defined storage. */
86         void data(const void *);
87
88         /** Replaces a range of bytes in the buffer.  Allocated storage must exist.
89         The range must be fully inside the buffer. */
90         void sub_data(std::size_t, std::size_t, const void *);
91
92         /** Creates an asynchronous transfer for writing data to a range of bytes in
93         the buffer.  While the transfer is pending, the state of the buffer region
94         is indeterminate. */
95         AsyncTransfer sub_data_async(std::size_t, std::size_t);
96
97 private:
98         void check_sub_data(std::size_t, std::size_t, const char *);
99
100 public:
101         std::size_t get_size() const { return size; }
102         using BufferBackend::get_multiplicity;
103         std::size_t get_total_size() const { return size*get_multiplicity(); }
104         BufferUsage get_usage() const { return usage; }
105
106         void require_size(std::size_t) const;
107
108         void *map();
109         bool unmap();
110
111         using BufferBackend::set_debug_name;
112 };
113
114 } // namespace GL
115 } // namespace Msp
116
117 #endif