Merge pull request #3992 from samcake/temp0

Add the BufferView class in gpu::Resource
This commit is contained in:
Brad Hefta-Gaub 2014-12-22 10:12:48 -08:00
commit fb15b0f2a7
10 changed files with 431 additions and 34 deletions

View file

@ -107,6 +107,19 @@ void Batch::setInputFormat(const Stream::FormatPointer& format) {
_params.push_back(_streamFormats.cache(format));
}
void Batch::setInputBuffer(Slot channel, const BufferPointer& buffer, Offset offset, Offset stride) {
ADD_COMMAND(setInputBuffer);
_params.push_back(stride);
_params.push_back(offset);
_params.push_back(_buffers.cache(buffer));
_params.push_back(channel);
}
void Batch::setInputBuffer(Slot channel, const BufferView& view) {
setInputBuffer(channel, view._buffer, view._offset, Offset(view._stride));
}
void Batch::setInputStream(Slot startChannel, const BufferStream& stream) {
if (stream.getNumBuffers()) {
const Buffers& buffers = stream.getBuffers();
@ -118,15 +131,6 @@ void Batch::setInputStream(Slot startChannel, const BufferStream& stream) {
}
}
void Batch::setInputBuffer(Slot channel, const BufferPointer& buffer, Offset offset, Offset stride) {
ADD_COMMAND(setInputBuffer);
_params.push_back(stride);
_params.push_back(offset);
_params.push_back(_buffers.cache(buffer));
_params.push_back(channel);
}
void Batch::setIndexBuffer(Type type, const BufferPointer& buffer, Offset offset) {
ADD_COMMAND(setIndexBuffer);
@ -153,3 +157,17 @@ void Batch::setProjectionTransform(const Transform& proj) {
_params.push_back(_transforms.cache(proj));
}
void Batch::setUniformBuffer(uint32 slot, const BufferPointer& buffer, Offset offset, Offset size) {
ADD_COMMAND(setUniformBuffer);
_params.push_back(size);
_params.push_back(offset);
_params.push_back(_buffers.cache(buffer));
_params.push_back(slot);
}
void Batch::setUniformBuffer(uint32 slot, const BufferView& view) {
setUniformBuffer(slot, view._buffer, view._offset, view._size);
}

View file

@ -72,8 +72,9 @@ public:
// IndexBuffer
void setInputFormat(const Stream::FormatPointer& format);
void setInputStream(Slot startChannel, const BufferStream& stream); // not a command, just unroll into a loop of setInputBuffer
void setInputBuffer(Slot channel, const BufferPointer& buffer, Offset offset, Offset stride);
void setInputBuffer(Slot channel, const BufferView& buffer); // not a command, just a shortcut from a BufferView
void setInputStream(Slot startChannel, const BufferStream& stream); // not a command, just unroll into a loop of setInputBuffer
void setIndexBuffer(Type type, const BufferPointer& buffer, Offset offset);
@ -87,6 +88,9 @@ public:
void setViewTransform(const Transform& view);
void setProjectionTransform(const Transform& proj);
// Shader Stage
void setUniformBuffer(uint32 slot, const BufferPointer& buffer, Offset offset, Offset size);
void setUniformBuffer(uint32 slot, const BufferView& view); // not a command, just a shortcut from a BufferView
// TODO: As long as we have gl calls explicitely issued from interface
// code, we need to be able to record and batch these calls. THe long
@ -117,6 +121,7 @@ public:
void _glUseProgram(GLuint program);
void _glUniform1f(GLint location, GLfloat v0);
void _glUniform2f(GLint location, GLfloat v0, GLfloat v1);
void _glUniform4fv(GLint location, GLsizei count, const GLfloat* value);
void _glUniformMatrix4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value);
void _glMatrixMode(GLenum mode);
@ -161,6 +166,8 @@ public:
COMMAND_setViewTransform,
COMMAND_setProjectionTransform,
COMMAND_setUniformBuffer,
// TODO: As long as we have gl calls explicitely issued from interface
// code, we need to be able to record and batch these calls. THe long
// term strategy is to get rid of any GL calls in favor of the HIFI GPU API
@ -187,6 +194,7 @@ public:
COMMAND_glUseProgram,
COMMAND_glUniform1f,
COMMAND_glUniform2f,
COMMAND_glUniform4fv,
COMMAND_glUniformMatrix4fv,
COMMAND_glMatrixMode,

View file

@ -12,7 +12,6 @@
#define hifi_gpu_Context_h
#include <assert.h>
#include "GPUConfig.h"
#include "Resource.h"

View file

@ -12,8 +12,6 @@
#define hifi_gpu_Format_h
#include <assert.h>
#include "GPUConfig.h"
namespace gpu {
@ -94,7 +92,8 @@ static const int DIMENSION_COUNT[NUM_DIMENSIONS] = {
// Semantic of an Element
// Provide information on how to use the element
enum Semantic {
RGB = 0,
RAW = 0, // used as RAW memory
RGB,
RGBA,
XYZ,
XYZW,
@ -104,6 +103,8 @@ enum Semantic {
DIR_XYZ,
UV,
R8,
INDEX, //used by index buffer of a mesh
PART, // used by part buffer of a mesh
NUM_SEMANTICS,
};
@ -119,7 +120,7 @@ public:
_type(type)
{}
Element() :
_semantic(R8),
_semantic(RAW),
_dimension(SCALAR),
_type(INT8)
{}

View file

@ -31,6 +31,8 @@ GLBackend::CommandCall GLBackend::_commandCalls[Batch::NUM_COMMANDS] =
(&::gpu::GLBackend::do_setViewTransform),
(&::gpu::GLBackend::do_setProjectionTransform),
(&::gpu::GLBackend::do_setUniformBuffer),
(&::gpu::GLBackend::do_glEnable),
(&::gpu::GLBackend::do_glDisable),
@ -54,6 +56,7 @@ GLBackend::CommandCall GLBackend::_commandCalls[Batch::NUM_COMMANDS] =
(&::gpu::GLBackend::do_glUseProgram),
(&::gpu::GLBackend::do_glUniform1f),
(&::gpu::GLBackend::do_glUniform2f),
(&::gpu::GLBackend::do_glUniform4fv),
(&::gpu::GLBackend::do_glUniformMatrix4fv),
(&::gpu::GLBackend::do_glMatrixMode),
@ -483,6 +486,25 @@ void GLBackend::updateTransform() {
}
}
void GLBackend::do_setUniformBuffer(Batch& batch, uint32 paramOffset) {
GLuint slot = batch._params[paramOffset + 3]._uint;
BufferPointer uniformBuffer = batch._buffers.get(batch._params[paramOffset + 2]._uint);
GLintptr rangeStart = batch._params[paramOffset + 1]._uint;
GLsizeiptr rangeSize = batch._params[paramOffset + 0]._uint;
#if defined(Q_OS_MAC)
GLfloat* data = (GLfloat*) (uniformBuffer->getData() + rangeStart);
glUniform4fv(slot, rangeSize / sizeof(GLfloat[4]), data);
#else
GLuint bo = getBufferID(*uniformBuffer);
glBindBufferRange(GL_UNIFORM_BUFFER, slot, bo, rangeStart, rangeSize);
// glUniformBufferEXT(_shader._program, slot, bo);
//glBindBufferBase(GL_UNIFORM_BUFFER, slot, bo);
#endif
CHECK_GL_ERROR();
}
// TODO: As long as we have gl calls explicitely issued from interface
// code, we need to be able to record and batch these calls. THe long
// term strategy is to get rid of any GL calls in favor of the HIFI GPU API
@ -672,7 +694,10 @@ void Batch::_glUseProgram(GLuint program) {
DO_IT_NOW(_glUseProgram, 1);
}
void GLBackend::do_glUseProgram(Batch& batch, uint32 paramOffset) {
glUseProgram(batch._params[paramOffset]._uint);
_shader._program = batch._params[paramOffset]._uint;
glUseProgram(_shader._program);
CHECK_GL_ERROR();
}
@ -708,6 +733,25 @@ void GLBackend::do_glUniform2f(Batch& batch, uint32 paramOffset) {
CHECK_GL_ERROR();
}
void Batch::_glUniform4fv(GLint location, GLsizei count, const GLfloat* value) {
ADD_COMMAND_GL(glUniform4fv);
const int VEC4_SIZE = 4 * sizeof(float);
_params.push_back(cacheData(count * VEC4_SIZE, value));
_params.push_back(count);
_params.push_back(location);
DO_IT_NOW(_glUniform4fv, 3);
}
void GLBackend::do_glUniform4fv(Batch& batch, uint32 paramOffset) {
glUniform4fv(
batch._params[paramOffset + 2]._int,
batch._params[paramOffset + 1]._uint,
(const GLfloat*)batch.editData(batch._params[paramOffset + 0]._uint));
CHECK_GL_ERROR();
}
void Batch::_glUniformMatrix4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value) {
ADD_COMMAND_GL(glUniformMatrix4fv);

View file

@ -122,6 +122,19 @@ protected:
_lastMode(GL_TEXTURE) {}
} _transform;
// Shader Stage
void do_setUniformBuffer(Batch& batch, uint32 paramOffset);
void updateShader();
struct ShaderStageState {
GLuint _program;
ShaderStageState() :
_program(0) {}
} _shader;
// TODO: As long as we have gl calls explicitely issued from interface
// code, we need to be able to record and batch these calls. THe long
// term strategy is to get rid of any GL calls in favor of the HIFI GPU API
@ -148,6 +161,7 @@ protected:
void do_glUseProgram(Batch& batch, uint32 paramOffset);
void do_glUniform1f(Batch& batch, uint32 paramOffset);
void do_glUniform2f(Batch& batch, uint32 paramOffset);
void do_glUniform4fv(Batch& batch, uint32 paramOffset);
void do_glUniformMatrix4fv(Batch& batch, uint32 paramOffset);
void do_glMatrixMode(Batch& batch, uint32 paramOffset);

View file

@ -67,6 +67,26 @@ Resource::Sysmem::Sysmem(Size size, const Byte* bytes) :
}
}
Resource::Sysmem::Sysmem(const Sysmem& sysmem) :
_stamp(0),
_size(0),
_data(NULL)
{
if (sysmem.getSize() > 0) {
_size = allocateMemory(&_data, sysmem.getSize());
if (_size >= sysmem.getSize()) {
if (sysmem.readData()) {
memcpy(_data, sysmem.readData(), sysmem.getSize());
}
}
}
}
Resource::Sysmem& Resource::Sysmem::operator=(const Sysmem& sysmem) {
setData(sysmem.getSize(), sysmem.readData());
return (*this);
}
Resource::Sysmem::~Sysmem() {
deallocateMemory( _data, _size );
_data = NULL;
@ -152,9 +172,25 @@ Resource::Size Resource::Sysmem::append(Size size, const Byte* bytes) {
Buffer::Buffer() :
Resource(),
_sysmem(NULL),
_sysmem(new Sysmem()),
_gpuObject(NULL) {
_sysmem = new Sysmem();
}
Buffer::Buffer(Size size, const Byte* bytes) :
Resource(),
_sysmem(new Sysmem(size, bytes)),
_gpuObject(NULL) {
}
Buffer::Buffer(const Buffer& buf) :
Resource(),
_sysmem(new Sysmem(buf.getSysmem())),
_gpuObject(NULL) {
}
Buffer& Buffer::operator=(const Buffer& buf) {
(*_sysmem) = buf.getSysmem();
return (*this);
}
Buffer::~Buffer() {

View file

@ -12,13 +12,15 @@
#define hifi_gpu_Resource_h
#include <assert.h>
#include "GPUConfig.h"
#include "Format.h"
#include <vector>
#include <QSharedPointer>
#ifdef _DEBUG
#include <QDebug>
#endif
namespace gpu {
@ -29,7 +31,7 @@ typedef int Stamp;
class Resource {
public:
typedef unsigned char Byte;
typedef unsigned int Size;
typedef unsigned int Size;
static const Size NOT_ALLOCATED = -1;
@ -47,6 +49,8 @@ protected:
Sysmem();
Sysmem(Size size, const Byte* bytes);
Sysmem(const Sysmem& sysmem); // deep copy of the sysmem buffer
Sysmem& operator=(const Sysmem& sysmem); // deep copy of the sysmem buffer
~Sysmem();
Size getSize() const { return _size; }
@ -90,9 +94,6 @@ protected:
static void deallocateMemory(Byte* memDeallocated, Size size);
private:
Sysmem(const Sysmem& sysmem) {}
Sysmem &operator=(const Sysmem& other) {return *this;}
Stamp _stamp;
Size _size;
Byte* _data;
@ -104,12 +105,15 @@ class Buffer : public Resource {
public:
Buffer();
Buffer(const Buffer& buf);
Buffer(Size size, const Byte* bytes);
Buffer(const Buffer& buf); // deep copy of the sysmem buffer
Buffer& operator=(const Buffer& buf); // deep copy of the sysmem buffer
~Buffer();
// The size in bytes of data stored in the buffer
Size getSize() const { return getSysmem().getSize(); }
const Byte* getData() const { return getSysmem().readData(); }
Byte* editData() { return editSysmem().editData(); }
// Resize the buffer
// Keep previous data [0 to min(pSize, mSize)]
@ -130,7 +134,7 @@ public:
// Access the sysmem object.
const Sysmem& getSysmem() const { assert(_sysmem); return (*_sysmem); }
Sysmem& editSysmem() { assert(_sysmem); return (*_sysmem); }
protected:
@ -138,8 +142,6 @@ protected:
mutable GPUObject* _gpuObject;
Sysmem& editSysmem() { assert(_sysmem); return (*_sysmem); }
// This shouldn't be used by anything else than the Backend class with the proper casting.
void setGPUObject(GPUObject* gpuObject) const { _gpuObject = gpuObject; }
GPUObject* getGPUObject() const { return _gpuObject; }
@ -149,6 +151,281 @@ protected:
typedef QSharedPointer<Buffer> BufferPointer;
typedef std::vector< BufferPointer > Buffers;
class BufferView {
public:
typedef Resource::Size Size;
typedef int Index;
BufferPointer _buffer;
Size _offset;
Size _size;
Element _element;
uint16 _stride;
BufferView() :
_buffer(NULL),
_offset(0),
_size(0),
_element(gpu::SCALAR, gpu::UINT8, gpu::RAW),
_stride(1)
{};
BufferView(const Element& element) :
_buffer(NULL),
_offset(0),
_size(0),
_element(element),
_stride(uint16(element.getSize()))
{};
// create the BufferView and own the Buffer
BufferView(Buffer* newBuffer, const Element& element = Element(gpu::SCALAR, gpu::UINT8, gpu::RAW)) :
_buffer(newBuffer),
_offset(0),
_size(newBuffer->getSize()),
_element(element),
_stride(uint16(element.getSize()))
{};
BufferView(const BufferPointer& buffer, const Element& element = Element(gpu::SCALAR, gpu::UINT8, gpu::RAW)) :
_buffer(buffer),
_offset(0),
_size(buffer->getSize()),
_element(element),
_stride(uint16(element.getSize()))
{};
BufferView(const BufferPointer& buffer, Size offset, Size size, const Element& element = Element(gpu::SCALAR, gpu::UINT8, gpu::RAW)) :
_buffer(buffer),
_offset(offset),
_size(size),
_element(element),
_stride(uint16(element.getSize()))
{};
~BufferView() {}
BufferView(const BufferView& view) = default;
BufferView& operator=(const BufferView& view) = default;
Size getNumElements() const { return _size / _element.getSize(); }
//Template iterator with random access on the buffer sysmem
template<typename T>
class Iterator : public std::iterator<std::random_access_iterator_tag,
T,
Index,
T*,
T&>
{
public:
Iterator(T* ptr = NULL) { _ptr = ptr; }
Iterator(const Iterator<T>& iterator) = default;
~Iterator() {}
Iterator<T>& operator=(const Iterator<T>& iterator) = default;
Iterator<T>& operator=(T* ptr) {
_ptr = ptr;
return (*this);
}
operator bool() const
{
if(_ptr)
return true;
else
return false;
}
bool operator==(const Iterator<T>& iterator) const { return (_ptr == iterator.getConstPtr()); }
bool operator!=(const Iterator<T>& iterator) const { return (_ptr != iterator.getConstPtr()); }
Iterator<T>& operator+=(const Index& movement) {
_ptr += movement;
return (*this);
}
Iterator<T>& operator-=(const Index& movement) {
_ptr -= movement;
return (*this);
}
Iterator<T>& operator++() {
++_ptr;
return (*this);
}
Iterator<T>& operator--() {
--_ptr;
return (*this);
}
Iterator<T> operator++(Index) {
auto temp(*this);
++_ptr;
return temp;
}
Iterator<T> operator--(Index) {
auto temp(*this);
--_ptr;
return temp;
}
Iterator<T> operator+(const Index& movement) {
auto oldPtr = _ptr;
_ptr += movement;
auto temp(*this);
_ptr = oldPtr;
return temp;
}
Iterator<T> operator-(const Index& movement) {
auto oldPtr = _ptr;
_ptr -= movement;
auto temp(*this);
_ptr = oldPtr;
return temp;
}
Index operator-(const Iterator<T>& iterator) { return (iterator.getPtr() - this->getPtr())/sizeof(T); }
T& operator*(){return *_ptr;}
const T& operator*()const{return *_ptr;}
T* operator->(){return _ptr;}
T* getPtr()const{return _ptr;}
const T* getConstPtr()const{return _ptr;}
protected:
T* _ptr;
};
template <typename T> Iterator<T> begin() { return Iterator<T>(&edit<T>(0)); }
template <typename T> Iterator<T> end() { return Iterator<T>(&edit<T>(getNum<T>())); }
template <typename T> Iterator<const T> cbegin() const { return Iterator<const T>(&get<T>(0)); }
template <typename T> Iterator<const T> cend() const { return Iterator<const T>(&get<T>(getNum<T>())); }
// the number of elements of the specified type fitting in the view size
template <typename T> Index getNum() const {
return Index(_size / sizeof(T));
}
template <typename T> const T& get() const {
#if _DEBUG
if (_buffer.isNull()) {
qDebug() << "Accessing null gpu::buffer!";
}
if (sizeof(T) > (_buffer->getSize() - _offset)) {
qDebug() << "Accessing buffer in non allocated memory, element size = " << sizeof(T) << " available space in buffer at offset is = " << (_buffer->getSize() - _offset);
}
if (sizeof(T) > _size) {
qDebug() << "Accessing buffer outside the BufferView range, element size = " << sizeof(T) << " when bufferView size = " << _size;
}
#endif
const T* t = (reinterpret_cast<const T*> (_buffer->getData() + _offset));
return *(t);
}
template <typename T> T& edit() {
#if _DEBUG
if (_buffer.isNull()) {
qDebug() << "Accessing null gpu::buffer!";
}
if (sizeof(T) > (_buffer->getSize() - _offset)) {
qDebug() << "Accessing buffer in non allocated memory, element size = " << sizeof(T) << " available space in buffer at offset is = " << (_buffer->getSize() - _offset);
}
if (sizeof(T) > _size) {
qDebug() << "Accessing buffer outside the BufferView range, element size = " << sizeof(T) << " when bufferView size = " << _size;
}
#endif
T* t = (reinterpret_cast<T*> (_buffer->editData() + _offset));
return *(t);
}
template <typename T> const T& get(const Index index) const {
Resource::Size elementOffset = index * sizeof(T) + _offset;
#if _DEBUG
if (_buffer.isNull()) {
qDebug() << "Accessing null gpu::buffer!";
}
if (sizeof(T) > (_buffer->getSize() - elementOffset)) {
qDebug() << "Accessing buffer in non allocated memory, index = " << index << ", element size = " << sizeof(T) << " available space in buffer at offset is = " << (_buffer->getSize() - elementOffset);
}
if (index > getNum<T>()) {
qDebug() << "Accessing buffer outside the BufferView range, index = " << index << " number elements = " << getNum<T>();
}
#endif
return *(reinterpret_cast<const T*> (_buffer->getData() + elementOffset));
}
template <typename T> T& edit(const Index index) const {
Resource::Size elementOffset = index * sizeof(T) + _offset;
#if _DEBUG
if (_buffer.isNull()) {
qDebug() << "Accessing null gpu::buffer!";
}
if (sizeof(T) > (_buffer->getSize() - elementOffset)) {
qDebug() << "Accessing buffer in non allocated memory, index = " << index << ", element size = " << sizeof(T) << " available space in buffer at offset is = " << (_buffer->getSize() - elementOffset);
}
if (index > getNum<T>()) {
qDebug() << "Accessing buffer outside the BufferView range, index = " << index << " number elements = " << getNum<T>();
}
#endif
return *(reinterpret_cast<T*> (_buffer->editData() + elementOffset));
}
};
// TODO: For now TextureView works with Buffer as a place holder for the Texture.
// The overall logic should be about the same except that the Texture will be a real GL Texture under the hood
class TextureView {
public:
typedef Resource::Size Size;
typedef int Index;
BufferPointer _buffer;
Size _offset;
Size _size;
Element _element;
uint16 _stride;
TextureView() :
_buffer(NULL),
_offset(0),
_size(0),
_element(gpu::VEC3, gpu::UINT8, gpu::RGB),
_stride(1)
{};
TextureView(const Element& element) :
_buffer(NULL),
_offset(0),
_size(0),
_element(element),
_stride(uint16(element.getSize()))
{};
// create the BufferView and own the Buffer
TextureView(Buffer* newBuffer, const Element& element) :
_buffer(newBuffer),
_offset(0),
_size(newBuffer->getSize()),
_element(element),
_stride(uint16(element.getSize()))
{};
TextureView(const BufferPointer& buffer, const Element& element) :
_buffer(buffer),
_offset(0),
_size(buffer->getSize()),
_element(element),
_stride(uint16(element.getSize()))
{};
TextureView(const BufferPointer& buffer, Size offset, Size size, const Element& element) :
_buffer(buffer),
_offset(offset),
_size(size),
_element(element),
_stride(uint16(element.getSize()))
{};
~TextureView() {}
TextureView(const TextureView& view) = default;
TextureView& operator=(const TextureView& view) = default;
};
};

View file

@ -18,7 +18,7 @@ void Stream::Format::evaluateCache() {
_elementTotalSize = 0;
for(AttributeMap::iterator it = _attributes.begin(); it != _attributes.end(); it++) {
Attribute& attrib = (*it).second;
Channel& channel = _channels[attrib._channel];
ChannelInfo& channel = _channels[attrib._channel];
channel._slots.push_back(attrib._slot);
channel._stride = std::max(channel._stride, attrib.getSize() + attrib._offset);
channel._netSize += attrib.getSize();
@ -41,7 +41,7 @@ BufferStream::BufferStream() :
BufferStream::~BufferStream() {
}
void BufferStream::addBuffer(BufferPointer& buffer, Offset offset, Offset stride) {
void BufferStream::addBuffer(const BufferPointer& buffer, Offset offset, Offset stride) {
_buffers.push_back(buffer);
_offsets.push_back(offset);
_strides.push_back(stride);

View file

@ -12,7 +12,6 @@
#define hifi_gpu_Stream_h
#include <assert.h>
#include "GPUConfig.h"
#include "Resource.h"
#include "Format.h"
@ -83,16 +82,16 @@ public:
public:
typedef std::map< Slot, Attribute > AttributeMap;
class Channel {
class ChannelInfo {
public:
std::vector< Slot > _slots;
std::vector< Offset > _offsets;
Offset _stride;
uint32 _netSize;
Channel() : _stride(0), _netSize(0) {}
ChannelInfo() : _stride(0), _netSize(0) {}
};
typedef std::map< Slot, Channel > ChannelMap;
typedef std::map< Slot, ChannelInfo > ChannelMap;
Format() :
_attributes(),
@ -104,6 +103,7 @@ public:
uint8 getNumChannels() const { return _channels.size(); }
const ChannelMap& getChannels() const { return _channels; }
const Offset getChannelStride(Slot channel) const { return _channels.at(channel)._stride; }
uint32 getElementTotalSize() const { return _elementTotalSize; }
@ -131,7 +131,7 @@ public:
BufferStream();
~BufferStream();
void addBuffer(BufferPointer& buffer, Offset offset, Offset stride);
void addBuffer(const BufferPointer& buffer, Offset offset, Offset stride);
const Buffers& getBuffers() const { return _buffers; }
const Offsets& getOffsets() const { return _offsets; }