X-Git-Url: http://git.tdb.fi/?p=libs%2Fgl.git;a=blobdiff_plain;f=source%2Fcore%2Fbuffer.h;h=9b1293615832a615318cf0212400c08b3af10961;hp=ad3084298c55e74e0cfb4296bab53a556c5cceae;hb=HEAD;hpb=2d3113a7dbbe4be2f1d1e8980c1c4e42175163da diff --git a/source/core/buffer.h b/source/core/buffer.h index ad308429..9b129361 100644 --- a/source/core/buffer.h +++ b/source/core/buffer.h @@ -3,13 +3,7 @@ #include #include -#include -#include -#include "gl.h" -#include -#include -#include -#include +#include "buffer_backend.h" namespace Msp { namespace GL { @@ -21,150 +15,100 @@ public: virtual ~buffer_too_small() throw() { } }; -enum BufferType -{ - ARRAY_BUFFER = GL_ARRAY_BUFFER, - ELEMENT_ARRAY_BUFFER = GL_ELEMENT_ARRAY_BUFFER, - PIXEL_PACK_BUFFER = GL_PIXEL_PACK_BUFFER, - PIXEL_UNPACK_BUFFER = GL_PIXEL_UNPACK_BUFFER, - UNIFORM_BUFFER = GL_UNIFORM_BUFFER -}; - enum BufferUsage { - STREAM_DRAW = GL_STREAM_DRAW, - STREAM_READ = GL_STREAM_READ, - STREAM_COPY = GL_STREAM_COPY, - STATIC_DRAW = GL_STATIC_DRAW, - STATIC_READ = GL_STATIC_READ, - STATIC_COPY = GL_STATIC_COPY, - DYNAMIC_DRAW = GL_DYNAMIC_DRAW, - DYNAMIC_READ = GL_DYNAMIC_READ, - DYNAMIC_COPY = GL_DYNAMIC_COPY + STATIC, + STREAMING }; -enum BufferAccess -{ - READ_ONLY = GL_READ_ONLY, - WRITE_ONLY = GL_WRITE_ONLY, - READ_WRITE = GL_READ_WRITE -}; +/** +Stores data in GPU memory. -class BufferRange; +Memory must be allocated for the buffer by calling storage(). Contents can +then be modified either synchronously with the data() and sub_data() functions, +or asynchronously by memory-mapping the buffer. -/** -A buffer for storing data in GL memory. Putting vertex and index data in -buffers can improve rendering performance. The VertexArray, Mesh and -UniformBlock classes contain built-in support for buffers. +Buffers can have a static or streaming usage pattern. Streaming buffers can be +memory mapped for less update overhead, but memory space is more limited. If +the buffer is updated only rarely, static is recommended. + +Applications normally don't need to deal with Buffers directly. They're +managed by other classes such as Mesh and ProgramData. */ -class Buffer +class Buffer: public BufferBackend { - friend class BufferRange; - -private: - BufferType type; - unsigned id; - unsigned size; - bool allocated; - - static const Buffer *bound[5]; + friend BufferBackend; public: - Buffer(BufferType); - ~Buffer(); + /** + An RAII handle for asynchronously writing data into a buffer. + */ + class AsyncTransfer: public NonCopyable + { + friend BufferBackend; + friend class Buffer; + + private: + Buffer *buffer = 0; + std::size_t offset = 0; + std::size_t size = 0; + void *dest_addr = 0; + + AsyncTransfer(Buffer &, std::size_t, std::size_t); + public: + AsyncTransfer() = default; + AsyncTransfer(AsyncTransfer &&); + AsyncTransfer &operator=(AsyncTransfer &&); + ~AsyncTransfer(); + + private: + void allocate(); + void finalize(); + + public: + /** Returns an address for writing the data. It should not be used + beyond the lifetime of the object. */ + void *get_address() { return dest_addr; } + }; private: - static void require_buffer_type(BufferType); + std::size_t size = 0; + BufferUsage usage = STATIC; + bool mapped = false; public: - /** Returns the OpenGL ID of the buffer. For internal use only. */ - unsigned get_id() const { return id; } - - /** Returns the default binding type for the buffer. */ - BufferType get_type() const { return type; } - - /** Defines the storage size of the buffer. Must be called before data can - be uploaded. Storage cannot be changed once set. */ - void storage(unsigned); - - /** Allocates storage for the buffer. The contents are initially undefined. - If storage has already been allocated, does nothing. */ - void allocate(); - - /** Sets the usage hint of the buffer. It will take effect the next time - the buffer's contents are defined. */ - DEPRECATED void set_usage(BufferUsage); + /** Sets storage size and usage pattern and allocates memory for the buffer. + Size and usage cannot be changed once set. */ + void storage(std::size_t, BufferUsage); - /** Uploads data into the buffer, completely replacing any previous - contents. Storage must be defined beforehand. The data must have size - matching the defined storage. */ + /** Replaces contents of the entire buffer. Allocated storage must exist. + The data must have size matching the defined storage. */ void data(const void *); - DEPRECATED void data(unsigned, const void *); - - /** Overwrites part of the buffer data with new data. Storage must be - defined beforehand. */ - void sub_data(unsigned, unsigned, const void *); - - unsigned get_size() const { return size; } - - void require_size(unsigned) const; - - BufferRange *create_range(unsigned, unsigned); - - void *map(); - DEPRECATED void *map(BufferAccess) { return map(); } - bool unmap(); - - /** Binds the buffer in its default slot. */ - void bind() const { bind_to(type); } - - /** Binds the buffer in an alternate slot. */ - void bind_to(BufferType) const; - - /** Unbinds the buffer from its default slot. */ - void unbind() const { unbind_from(type); } - - static const Buffer *current(BufferType); - static void unbind_from(BufferType); -private: - static const Buffer *&binding(BufferType); - static bool set_current(BufferType, const Buffer *); - -public: - void set_debug_name(const std::string &); -}; + /** Replaces a range of bytes in the buffer. Allocated storage must exist. + The range must be fully inside the buffer. */ + void sub_data(std::size_t, std::size_t, const void *); + /** Creates an asynchronous transfer for writing data to a range of bytes in + the buffer. While the transfer is pending, the state of the buffer region + is indeterminate. */ + AsyncTransfer sub_data_async(std::size_t, std::size_t); -/** -A proxy for a subset of a buffer. Can be bound for use with uniform blocks. -*/ -class BufferRange -{ private: - Buffer &buffer; - unsigned offset; - unsigned size; - - static std::vector bound_uniform; + void check_sub_data(std::size_t, std::size_t, const char *); public: - BufferRange(Buffer &, unsigned, unsigned); - ~BufferRange(); - - void data(const void *); + std::size_t get_size() const { return size; } + using BufferBackend::get_multiplicity; + std::size_t get_total_size() const { return size*get_multiplicity(); } + BufferUsage get_usage() const { return usage; } - void bind_to(BufferType, unsigned); + void require_size(std::size_t) const; - static const BufferRange *current(BufferType t, unsigned i) { return binding(t, i); } - static void unbind_from(BufferType, unsigned); -private: - static const BufferRange *&binding(BufferType, unsigned); - static bool set_current(BufferType, unsigned, const BufferRange *); + void *map(); + bool unmap(); -public: - DEPRECATED static unsigned get_n_uniform_buffer_bindings(); - DEPRECATED static unsigned get_uniform_buffer_alignment(); + using BufferBackend::set_debug_name; }; } // namespace GL