mirror of
https://github.com/JulianGro/overte.git
synced 2025-04-25 19:55:07 +02:00
Merge pull request #5331 from samcake/punk
Caching the input buffers' gpuObject in GLBackend
This commit is contained in:
commit
b18dd54c10
6 changed files with 201 additions and 94 deletions
|
@ -40,11 +40,8 @@
|
|||
namespace gpu {
|
||||
|
||||
enum ReservedSlot {
|
||||
/* TRANSFORM_OBJECT_SLOT = 6,
|
||||
TRANSFORM_OBJECT_SLOT = 6,
|
||||
TRANSFORM_CAMERA_SLOT = 7,
|
||||
*/
|
||||
TRANSFORM_OBJECT_SLOT = 1,
|
||||
TRANSFORM_CAMERA_SLOT = 2,
|
||||
};
|
||||
|
||||
class Batch {
|
||||
|
|
|
@ -87,10 +87,12 @@ GLBackend::GLBackend() :
|
|||
_pipeline(),
|
||||
_output()
|
||||
{
|
||||
initInput();
|
||||
initTransform();
|
||||
}
|
||||
|
||||
GLBackend::~GLBackend() {
|
||||
killInput();
|
||||
killTransform();
|
||||
}
|
||||
|
||||
|
|
|
@ -228,7 +228,21 @@ public:
|
|||
|
||||
void do_setStateColorWriteMask(uint32 mask);
|
||||
|
||||
// Repporting stats of the context
|
||||
class Stats {
|
||||
public:
|
||||
int _ISNumFormatChanges = 0;
|
||||
int _ISNumInputBufferChanges = 0;
|
||||
int _ISNumIndexBufferChanges = 0;
|
||||
|
||||
Stats() {}
|
||||
Stats(const Stats& stats) = default;
|
||||
};
|
||||
|
||||
void getStats(Stats& stats) const { stats = _stats; }
|
||||
|
||||
protected:
|
||||
Stats _stats;
|
||||
|
||||
// Draw Stage
|
||||
void do_draw(Batch& batch, uint32 paramOffset);
|
||||
|
@ -242,12 +256,13 @@ protected:
|
|||
void do_setInputFormat(Batch& batch, uint32 paramOffset);
|
||||
void do_setInputBuffer(Batch& batch, uint32 paramOffset);
|
||||
void do_setIndexBuffer(Batch& batch, uint32 paramOffset);
|
||||
|
||||
// Synchronize the state cache of this Backend with the actual real state of the GL Context
|
||||
|
||||
void initInput();
|
||||
void killInput();
|
||||
void syncInputStateCache();
|
||||
void updateInput();
|
||||
struct InputStageState {
|
||||
bool _invalidFormat;
|
||||
bool _invalidFormat = true;
|
||||
Stream::FormatPointer _format;
|
||||
|
||||
typedef std::bitset<MAX_NUM_INPUT_BUFFERS> BuffersState;
|
||||
|
@ -256,6 +271,7 @@ protected:
|
|||
Buffers _buffers;
|
||||
Offsets _bufferOffsets;
|
||||
Offsets _bufferStrides;
|
||||
std::vector<GLuint> _bufferVBOs;
|
||||
|
||||
BufferPointer _indexBuffer;
|
||||
Offset _indexBufferOffset;
|
||||
|
@ -264,6 +280,8 @@ protected:
|
|||
typedef std::bitset<MAX_NUM_ATTRIBUTES> ActivationCache;
|
||||
ActivationCache _attributeActivation;
|
||||
|
||||
GLuint _defaultVAO;
|
||||
|
||||
InputStageState() :
|
||||
_invalidFormat(true),
|
||||
_format(0),
|
||||
|
@ -271,10 +289,12 @@ protected:
|
|||
_buffers(_buffersState.size(), BufferPointer(0)),
|
||||
_bufferOffsets(_buffersState.size(), 0),
|
||||
_bufferStrides(_buffersState.size(), 0),
|
||||
_bufferVBOs(_buffersState.size(), 0),
|
||||
_indexBuffer(0),
|
||||
_indexBufferOffset(0),
|
||||
_indexBufferType(UINT32),
|
||||
_attributeActivation(0)
|
||||
_attributeActivation(0),
|
||||
_defaultVAO(0)
|
||||
{}
|
||||
} _input;
|
||||
|
||||
|
|
|
@ -28,13 +28,39 @@ void GLBackend::do_setInputBuffer(Batch& batch, uint32 paramOffset) {
|
|||
uint32 channel = batch._params[paramOffset + 3]._uint;
|
||||
|
||||
if (channel < getNumInputBuffers()) {
|
||||
_input._buffers[channel] = buffer;
|
||||
_input._bufferOffsets[channel] = offset;
|
||||
_input._bufferStrides[channel] = stride;
|
||||
_input._buffersState.set(channel);
|
||||
bool isModified = false;
|
||||
if (_input._buffers[channel] != buffer) {
|
||||
_input._buffers[channel] = buffer;
|
||||
|
||||
GLuint vbo = 0;
|
||||
if (buffer) {
|
||||
vbo = getBufferID((*buffer));
|
||||
}
|
||||
_input._bufferVBOs[channel] = vbo;
|
||||
|
||||
isModified = true;
|
||||
}
|
||||
|
||||
if (_input._bufferOffsets[channel] != offset) {
|
||||
_input._bufferOffsets[channel] = offset;
|
||||
isModified = true;
|
||||
}
|
||||
|
||||
if (_input._bufferStrides[channel] != stride) {
|
||||
_input._bufferStrides[channel] = stride;
|
||||
isModified = true;
|
||||
}
|
||||
|
||||
if (isModified) {
|
||||
_input._buffersState.set(channel);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#define NOT_SUPPORT_VAO
|
||||
#if defined(SUPPORT_VAO)
|
||||
#else
|
||||
|
||||
#define SUPPORT_LEGACY_OPENGL
|
||||
#if defined(SUPPORT_LEGACY_OPENGL)
|
||||
static const int NUM_CLASSIC_ATTRIBS = Stream::TANGENT;
|
||||
|
@ -45,24 +71,120 @@ static const GLenum attributeSlotToClassicAttribName[NUM_CLASSIC_ATTRIBS] = {
|
|||
GL_TEXTURE_COORD_ARRAY
|
||||
};
|
||||
#endif
|
||||
#endif
|
||||
|
||||
void GLBackend::initInput() {
|
||||
#if defined(SUPPORT_VAO)
|
||||
if(!_input._defaultVAO) {
|
||||
glGenVertexArrays(1, &_input._defaultVAO);
|
||||
}
|
||||
glBindVertexArray(_input._defaultVAO);
|
||||
(void) CHECK_GL_ERROR();
|
||||
#endif
|
||||
}
|
||||
|
||||
void GLBackend::killInput() {
|
||||
#if defined(SUPPORT_VAO)
|
||||
glBindVertexArray(0);
|
||||
if(_input._defaultVAO) {
|
||||
glDeleteVertexArrays(1, &_input._defaultVAO);
|
||||
}
|
||||
(void) CHECK_GL_ERROR();
|
||||
#endif
|
||||
}
|
||||
|
||||
void GLBackend::syncInputStateCache() {
|
||||
#if defined(SUPPORT_VAO)
|
||||
for (int i = 0; i < NUM_CLASSIC_ATTRIBS; i++) {
|
||||
_input._attributeActivation[i] = glIsEnabled(attributeSlotToClassicAttribName[i]);
|
||||
}
|
||||
//_input._defaultVAO
|
||||
glBindVertexArray(_input._defaultVAO);
|
||||
#else
|
||||
int i = 0;
|
||||
#if defined(SUPPORT_LEGACY_OPENGL)
|
||||
for (; i < NUM_CLASSIC_ATTRIBS; i++) {
|
||||
_input._attributeActivation[i] = glIsEnabled(attributeSlotToClassicAttribName[i]);
|
||||
}
|
||||
#endif
|
||||
for (; i < _input._attributeActivation.size(); i++) {
|
||||
GLint active = 0;
|
||||
glGetVertexAttribiv(i, GL_VERTEX_ATTRIB_ARRAY_ENABLED, &active);
|
||||
_input._attributeActivation[i] = active;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void GLBackend::updateInput() {
|
||||
#if defined(SUPPORT_VAO)
|
||||
if (_input._invalidFormat) {
|
||||
|
||||
InputStageState::ActivationCache newActivation;
|
||||
|
||||
// Assign the vertex format required
|
||||
if (_input._format) {
|
||||
for (auto& it : _input._format->getAttributes()) {
|
||||
const Stream::Attribute& attrib = (it).second;
|
||||
newActivation.set(attrib._slot);
|
||||
glVertexAttribFormat(
|
||||
attrib._slot,
|
||||
attrib._element.getDimensionCount(),
|
||||
_elementTypeToGLType[attrib._element.getType()],
|
||||
attrib._element.isNormalized(),
|
||||
attrib._offset);
|
||||
}
|
||||
(void) CHECK_GL_ERROR();
|
||||
}
|
||||
|
||||
// Manage Activation what was and what is expected now
|
||||
for (int i = 0; i < newActivation.size(); i++) {
|
||||
bool newState = newActivation[i];
|
||||
if (newState != _input._attributeActivation[i]) {
|
||||
if (newState) {
|
||||
glEnableVertexAttribArray(i);
|
||||
} else {
|
||||
glDisableVertexAttribArray(i);
|
||||
}
|
||||
_input._attributeActivation.flip(i);
|
||||
}
|
||||
}
|
||||
(void) CHECK_GL_ERROR();
|
||||
|
||||
_input._invalidFormat = false;
|
||||
_stats._ISNumFormatChanges++;
|
||||
}
|
||||
|
||||
if (_input._buffersState.any()) {
|
||||
int numBuffers = _input._buffers.size();
|
||||
auto buffer = _input._buffers.data();
|
||||
auto vbo = _input._bufferVBOs.data();
|
||||
auto offset = _input._bufferOffsets.data();
|
||||
auto stride = _input._bufferStrides.data();
|
||||
|
||||
for (int bufferNum = 0; bufferNum < numBuffers; bufferNum++) {
|
||||
if (_input._buffersState.test(bufferNum)) {
|
||||
glBindVertexBuffer(bufferNum, (*vbo), (*offset), (*stride));
|
||||
}
|
||||
buffer++;
|
||||
vbo++;
|
||||
offset++;
|
||||
stride++;
|
||||
}
|
||||
_input._buffersState.reset();
|
||||
(void) CHECK_GL_ERROR();
|
||||
}
|
||||
#else
|
||||
if (_input._invalidFormat || _input._buffersState.any()) {
|
||||
|
||||
if (_input._invalidFormat) {
|
||||
InputStageState::ActivationCache newActivation;
|
||||
|
||||
_stats._ISNumFormatChanges++;
|
||||
|
||||
// Check expected activation
|
||||
if (_input._format) {
|
||||
const Stream::Format::AttributeMap& attributes = _input._format->getAttributes();
|
||||
for (Stream::Format::AttributeMap::const_iterator it = attributes.begin(); it != attributes.end(); it++) {
|
||||
const Stream::Attribute& attrib = (*it).second;
|
||||
for (auto& it : _input._format->getAttributes()) {
|
||||
const Stream::Attribute& attrib = (it).second;
|
||||
newActivation.set(attrib._slot);
|
||||
}
|
||||
}
|
||||
|
@ -72,17 +194,15 @@ void GLBackend::updateInput() {
|
|||
bool newState = newActivation[i];
|
||||
if (newState != _input._attributeActivation[i]) {
|
||||
#if defined(SUPPORT_LEGACY_OPENGL)
|
||||
const bool useClientState = i < NUM_CLASSIC_ATTRIBS;
|
||||
#else
|
||||
const bool useClientState = false;
|
||||
#endif
|
||||
if (useClientState) {
|
||||
if (i < NUM_CLASSIC_ATTRIBS) {
|
||||
if (newState) {
|
||||
glEnableClientState(attributeSlotToClassicAttribName[i]);
|
||||
} else {
|
||||
glDisableClientState(attributeSlotToClassicAttribName[i]);
|
||||
}
|
||||
} else {
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
if (newState) {
|
||||
glEnableVertexAttribArray(i);
|
||||
} else {
|
||||
|
@ -103,18 +223,23 @@ void GLBackend::updateInput() {
|
|||
const Offsets& strides = _input._bufferStrides;
|
||||
|
||||
const Stream::Format::AttributeMap& attributes = _input._format->getAttributes();
|
||||
auto& inputChannels = _input._format->getChannels();
|
||||
_stats._ISNumInputBufferChanges++;
|
||||
|
||||
for (Stream::Format::ChannelMap::const_iterator channelIt = _input._format->getChannels().begin();
|
||||
channelIt != _input._format->getChannels().end();
|
||||
channelIt++) {
|
||||
const Stream::Format::ChannelMap::value_type::second_type& channel = (*channelIt).second;
|
||||
if ((*channelIt).first < buffers.size()) {
|
||||
int bufferNum = (*channelIt).first;
|
||||
GLuint boundVBO = 0;
|
||||
for (auto& channelIt : inputChannels) {
|
||||
const Stream::Format::ChannelMap::value_type::second_type& channel = (channelIt).second;
|
||||
if ((channelIt).first < buffers.size()) {
|
||||
int bufferNum = (channelIt).first;
|
||||
|
||||
if (_input._buffersState.test(bufferNum) || _input._invalidFormat) {
|
||||
GLuint vbo = gpu::GLBackend::getBufferID((*buffers[bufferNum]));
|
||||
glBindBuffer(GL_ARRAY_BUFFER, vbo);
|
||||
(void) CHECK_GL_ERROR();
|
||||
// GLuint vbo = gpu::GLBackend::getBufferID((*buffers[bufferNum]));
|
||||
GLuint vbo = _input._bufferVBOs[bufferNum];
|
||||
if (boundVBO != vbo) {
|
||||
glBindBuffer(GL_ARRAY_BUFFER, vbo);
|
||||
(void) CHECK_GL_ERROR();
|
||||
boundVBO = vbo;
|
||||
}
|
||||
_input._buffersState[bufferNum] = false;
|
||||
|
||||
for (unsigned int i = 0; i < channel._slots.size(); i++) {
|
||||
|
@ -126,9 +251,6 @@ void GLBackend::updateInput() {
|
|||
GLuint pointer = attrib._offset + offsets[bufferNum];
|
||||
#if defined(SUPPORT_LEGACY_OPENGL)
|
||||
const bool useClientState = slot < NUM_CLASSIC_ATTRIBS;
|
||||
#else
|
||||
const bool useClientState = false;
|
||||
#endif
|
||||
if (useClientState) {
|
||||
switch (slot) {
|
||||
case Stream::POSITION:
|
||||
|
@ -144,7 +266,9 @@ void GLBackend::updateInput() {
|
|||
glTexCoordPointer(count, type, stride, reinterpret_cast<GLvoid*>(pointer));
|
||||
break;
|
||||
};
|
||||
} else {
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
GLboolean isNormalized = attrib._element.isNormalized();
|
||||
glVertexAttribPointer(slot, count, type, isNormalized, stride,
|
||||
reinterpret_cast<GLvoid*>(pointer));
|
||||
|
@ -158,61 +282,7 @@ void GLBackend::updateInput() {
|
|||
// everything format related should be in sync now
|
||||
_input._invalidFormat = false;
|
||||
}
|
||||
|
||||
/* TODO: Fancy version GL4.4
|
||||
if (_needInputFormatUpdate) {
|
||||
|
||||
InputActivationCache newActivation;
|
||||
|
||||
// Assign the vertex format required
|
||||
if (_inputFormat) {
|
||||
const StreamFormat::AttributeMap& attributes = _inputFormat->getAttributes();
|
||||
for (StreamFormat::AttributeMap::const_iterator it = attributes.begin(); it != attributes.end(); it++) {
|
||||
const StreamFormat::Attribute& attrib = (*it).second;
|
||||
newActivation.set(attrib._slot);
|
||||
glVertexAttribFormat(
|
||||
attrib._slot,
|
||||
attrib._element.getDimensionCount(),
|
||||
_elementTypeToGLType[attrib._element.getType()],
|
||||
attrib._element.isNormalized(),
|
||||
attrib._stride);
|
||||
}
|
||||
CHECK_GL_ERROR();
|
||||
}
|
||||
|
||||
// Manage Activation what was and what is expected now
|
||||
for (int i = 0; i < newActivation.size(); i++) {
|
||||
bool newState = newActivation[i];
|
||||
if (newState != _inputAttributeActivation[i]) {
|
||||
if (newState) {
|
||||
glEnableVertexAttribArray(i);
|
||||
} else {
|
||||
glDisableVertexAttribArray(i);
|
||||
}
|
||||
_inputAttributeActivation.flip(i);
|
||||
}
|
||||
}
|
||||
CHECK_GL_ERROR();
|
||||
|
||||
_needInputFormatUpdate = false;
|
||||
}
|
||||
|
||||
if (_needInputStreamUpdate) {
|
||||
if (_inputStream) {
|
||||
const Stream::Buffers& buffers = _inputStream->getBuffers();
|
||||
const Stream::Offsets& offsets = _inputStream->getOffsets();
|
||||
const Stream::Strides& strides = _inputStream->getStrides();
|
||||
|
||||
for (int i = 0; i < buffers.size(); i++) {
|
||||
GLuint vbo = gpu::GLBackend::getBufferID((*buffers[i]));
|
||||
glBindVertexBuffer(i, vbo, offsets[i], strides[i]);
|
||||
}
|
||||
|
||||
CHECK_GL_ERROR();
|
||||
}
|
||||
_needInputStreamUpdate = false;
|
||||
}
|
||||
*/
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -41,21 +41,34 @@ void makeBindings(GLBackend::GLShader* shader) {
|
|||
glBindAttribLocation(glprogram, gpu::Stream::POSITION, "position");
|
||||
}
|
||||
|
||||
loc = glGetAttribLocation(glprogram, "attribPosition");
|
||||
if (loc >= 0) {
|
||||
glBindAttribLocation(glprogram, gpu::Stream::POSITION, "attribPosition");
|
||||
}
|
||||
|
||||
//Check for gpu specific attribute slotBindings
|
||||
loc = glGetAttribLocation(glprogram, "gl_Vertex");
|
||||
if (loc >= 0) {
|
||||
glBindAttribLocation(glprogram, gpu::Stream::POSITION, "position");
|
||||
glBindAttribLocation(glprogram, gpu::Stream::POSITION, "gl_Vertex");
|
||||
}
|
||||
|
||||
loc = glGetAttribLocation(glprogram, "normal");
|
||||
if (loc >= 0) {
|
||||
glBindAttribLocation(glprogram, gpu::Stream::NORMAL, "normal");
|
||||
}
|
||||
loc = glGetAttribLocation(glprogram, "attribNormal");
|
||||
if (loc >= 0) {
|
||||
glBindAttribLocation(glprogram, gpu::Stream::NORMAL, "attribNormal");
|
||||
}
|
||||
|
||||
loc = glGetAttribLocation(glprogram, "color");
|
||||
if (loc >= 0) {
|
||||
glBindAttribLocation(glprogram, gpu::Stream::COLOR, "color");
|
||||
}
|
||||
loc = glGetAttribLocation(glprogram, "attribColor");
|
||||
if (loc >= 0) {
|
||||
glBindAttribLocation(glprogram, gpu::Stream::COLOR, "attribColor");
|
||||
}
|
||||
|
||||
loc = glGetAttribLocation(glprogram, "texcoord");
|
||||
if (loc >= 0) {
|
||||
|
@ -75,6 +88,10 @@ void makeBindings(GLBackend::GLShader* shader) {
|
|||
if (loc >= 0) {
|
||||
glBindAttribLocation(glprogram, gpu::Stream::TEXCOORD1, "texcoord1");
|
||||
}
|
||||
loc = glGetAttribLocation(glprogram, "attribTexcoord1");
|
||||
if (loc >= 0) {
|
||||
glBindAttribLocation(glprogram, gpu::Stream::TEXCOORD1, "texcoord1");
|
||||
}
|
||||
|
||||
loc = glGetAttribLocation(glprogram, "clusterIndices");
|
||||
if (loc >= 0) {
|
||||
|
|
|
@ -82,8 +82,6 @@ void GLBackend::syncTransformStateCache() {
|
|||
}
|
||||
|
||||
void GLBackend::updateTransform() {
|
||||
GLint originalMatrixMode;
|
||||
glGetIntegerv(GL_MATRIX_MODE, &originalMatrixMode);
|
||||
// Check all the dirty flags and update the state accordingly
|
||||
if (_transform._invalidViewport) {
|
||||
_transform._transformCamera._viewport = glm::vec4(_transform._viewport);
|
||||
|
@ -138,6 +136,9 @@ void GLBackend::updateTransform() {
|
|||
|
||||
#if (GPU_TRANSFORM_PROFILE == GPU_LEGACY)
|
||||
// Do it again for fixed pipeline until we can get rid of it
|
||||
GLint originalMatrixMode;
|
||||
glGetIntegerv(GL_MATRIX_MODE, &originalMatrixMode);
|
||||
|
||||
if (_transform._invalidProj) {
|
||||
if (_transform._lastMode != GL_PROJECTION) {
|
||||
glMatrixMode(GL_PROJECTION);
|
||||
|
@ -173,12 +174,12 @@ void GLBackend::updateTransform() {
|
|||
}
|
||||
(void) CHECK_GL_ERROR();
|
||||
}
|
||||
|
||||
glMatrixMode(originalMatrixMode);
|
||||
#endif
|
||||
|
||||
// Flags are clean
|
||||
_transform._invalidView = _transform._invalidProj = _transform._invalidModel = _transform._invalidViewport = false;
|
||||
|
||||
glMatrixMode(originalMatrixMode);
|
||||
}
|
||||
|
||||
|
||||
|
|
Loading…
Reference in a new issue