mirror of
https://github.com/baldurk/renderdoc.git
synced 2026-08-15 19:16:32 +00:00
Move bound vertex buffers from general state to VAO state
This commit is contained in:
@@ -170,6 +170,39 @@ GLenum ShaderEnum(size_t idx)
|
||||
return eGL_NONE;
|
||||
}
|
||||
|
||||
GLuint GetBoundVertexBuffer(const GLHookSet &gl, GLuint i)
|
||||
{
|
||||
static int hackAMDBugVBBinding = -1;
|
||||
|
||||
// linux AMD driver doesn't recognise GL_VERTEX_BINDING_BUFFER, see below.
|
||||
if(hackAMDBugVBBinding == -1)
|
||||
{
|
||||
GLenum err = gl.glGetError();
|
||||
while(err != eGL_NONE) err = gl.glGetError();
|
||||
GLint dummy = 0;
|
||||
gl.glGetIntegeri_v(eGL_VERTEX_BINDING_BUFFER, 0, &dummy);
|
||||
err = gl.glGetError();
|
||||
|
||||
hackAMDBugVBBinding = (err == eGL_NONE ? 0 : 1);
|
||||
|
||||
if(hackAMDBugVBBinding)
|
||||
RDCWARN("Using AMD hack to avoid GL_VERTEX_BINDING_BUFFER");
|
||||
}
|
||||
|
||||
GLuint buffer = 0;
|
||||
|
||||
// the linux AMD driver has a "two wrongs make a right" type deal. Instead of returning the buffer that the
|
||||
// i'th index is bound to (as above, vbslot) for GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING, it returns the i'th
|
||||
// vertex buffer which is exactly what we wanted from GL_VERTEX_BINDING_BUFFER!
|
||||
// see: http://devgurus.amd.com/message/1306745#1306745
|
||||
if(hackAMDBugVBBinding)
|
||||
gl.glGetVertexAttribiv(i, eGL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING, (GLint *)&buffer);
|
||||
else
|
||||
gl.glGetIntegeri_v(eGL_VERTEX_BINDING_BUFFER, i, (GLint *)&buffer);
|
||||
|
||||
return buffer;
|
||||
}
|
||||
|
||||
ResourceFormat MakeResourceFormat(WrappedOpenGL &gl, GLenum target, GLenum fmt)
|
||||
{
|
||||
ResourceFormat ret;
|
||||
|
||||
@@ -82,6 +82,8 @@ GLenum ShaderEnum(size_t idx);
|
||||
ResourceFormat MakeResourceFormat(WrappedOpenGL &gl, GLenum target, GLenum fmt);
|
||||
GLenum MakeGLFormat(WrappedOpenGL &gl, GLenum target, ResourceFormat fmt);
|
||||
|
||||
GLuint GetBoundVertexBuffer(const GLHookSet &gl, GLuint idx);
|
||||
|
||||
extern int GLCoreVersion;
|
||||
void UpdateExtensionSupport(const GLHookSet &gl);
|
||||
bool ExtensionSupported(const char *ext);
|
||||
|
||||
@@ -26,9 +26,9 @@
|
||||
#include "driver/gl/gl_manager.h"
|
||||
#include "driver/gl/gl_driver.h"
|
||||
|
||||
struct VertexArrayInitialData
|
||||
struct VertexAttribInitialData
|
||||
{
|
||||
VertexArrayInitialData()
|
||||
VertexAttribInitialData()
|
||||
{
|
||||
RDCEraseEl(*this);
|
||||
}
|
||||
@@ -41,8 +41,26 @@ struct VertexArrayInitialData
|
||||
uint32_t size;
|
||||
};
|
||||
|
||||
struct VertexBufferInitialData
|
||||
{
|
||||
VertexBufferInitialData()
|
||||
{
|
||||
RDCEraseEl(*this);
|
||||
}
|
||||
ResourceId Buffer;
|
||||
uint64_t Stride;
|
||||
uint64_t Offset;
|
||||
uint32_t Divisor;
|
||||
};
|
||||
|
||||
struct VAOInitialData
|
||||
{
|
||||
VertexAttribInitialData VertexAttribs[16];
|
||||
VertexBufferInitialData VertexBuffers[16];
|
||||
};
|
||||
|
||||
template<>
|
||||
void Serialiser::Serialise(const char *name, VertexArrayInitialData &el)
|
||||
void Serialiser::Serialise(const char *name, VertexAttribInitialData &el)
|
||||
{
|
||||
ScopedContext scope(this, this, name, "VertexArrayInitialData", 0, true);
|
||||
Serialise("enabled", el.enabled);
|
||||
@@ -54,6 +72,16 @@ void Serialiser::Serialise(const char *name, VertexArrayInitialData &el)
|
||||
Serialise("size", el.size);
|
||||
}
|
||||
|
||||
template<>
|
||||
void Serialiser::Serialise(const char *name, VertexBufferInitialData &el)
|
||||
{
|
||||
ScopedContext scope(this, this, name, "VertexBufferInitialData", 0, true);
|
||||
Serialise("Buffer", el.Buffer);
|
||||
Serialise("Stride", el.Stride);
|
||||
Serialise("Offset", el.Offset);
|
||||
Serialise("Divisor", el.Divisor);
|
||||
}
|
||||
|
||||
struct TextureStateInitialData
|
||||
{
|
||||
TextureStateInitialData()
|
||||
@@ -240,17 +268,25 @@ bool GLResourceManager::Prepare_InitialState(GLResource res)
|
||||
|
||||
gl.glBindVertexArray(res.name);
|
||||
|
||||
VertexArrayInitialData *data = (VertexArrayInitialData *)Serialiser::AllocAlignedBuffer(sizeof(VertexArrayInitialData)*16);
|
||||
|
||||
VAOInitialData *data = (VAOInitialData *)Serialiser::AllocAlignedBuffer(sizeof(VAOInitialData));
|
||||
|
||||
for(GLuint i=0; i < 16; i++)
|
||||
{
|
||||
gl.glGetVertexAttribiv(i, eGL_VERTEX_ATTRIB_ARRAY_ENABLED, (GLint *)&data[i].enabled);
|
||||
gl.glGetVertexAttribiv(i, eGL_VERTEX_ATTRIB_BINDING, (GLint *)&data[i].vbslot);
|
||||
gl.glGetVertexAttribiv(i, eGL_VERTEX_ATTRIB_RELATIVE_OFFSET, (GLint*)&data[i].offset);
|
||||
gl.glGetVertexAttribiv(i, eGL_VERTEX_ATTRIB_ARRAY_TYPE, (GLint *)&data[i].type);
|
||||
gl.glGetVertexAttribiv(i, eGL_VERTEX_ATTRIB_ARRAY_NORMALIZED, (GLint *)&data[i].normalized);
|
||||
gl.glGetVertexAttribiv(i, eGL_VERTEX_ATTRIB_ARRAY_INTEGER, (GLint *)&data[i].integer);
|
||||
gl.glGetVertexAttribiv(i, eGL_VERTEX_ATTRIB_ARRAY_SIZE, (GLint *)&data[i].size);
|
||||
gl.glGetVertexAttribiv(i, eGL_VERTEX_ATTRIB_ARRAY_ENABLED, (GLint *)&data->VertexAttribs[i].enabled);
|
||||
gl.glGetVertexAttribiv(i, eGL_VERTEX_ATTRIB_BINDING, (GLint *)&data->VertexAttribs[i].vbslot);
|
||||
gl.glGetVertexAttribiv(i, eGL_VERTEX_ATTRIB_RELATIVE_OFFSET, (GLint*)&data->VertexAttribs[i].offset);
|
||||
gl.glGetVertexAttribiv(i, eGL_VERTEX_ATTRIB_ARRAY_TYPE, (GLint *)&data->VertexAttribs[i].type);
|
||||
gl.glGetVertexAttribiv(i, eGL_VERTEX_ATTRIB_ARRAY_NORMALIZED, (GLint *)&data->VertexAttribs[i].normalized);
|
||||
gl.glGetVertexAttribiv(i, eGL_VERTEX_ATTRIB_ARRAY_INTEGER, (GLint *)&data->VertexAttribs[i].integer);
|
||||
gl.glGetVertexAttribiv(i, eGL_VERTEX_ATTRIB_ARRAY_SIZE, (GLint *)&data->VertexAttribs[i].size);
|
||||
|
||||
GLuint buffer = GetBoundVertexBuffer(gl, i);
|
||||
|
||||
data->VertexBuffers[i].Buffer = GetID(BufferRes(res.Context, buffer));
|
||||
|
||||
gl.glGetIntegeri_v(eGL_VERTEX_BINDING_STRIDE, i, (GLint *)&data->VertexBuffers[i].Stride);
|
||||
gl.glGetIntegeri_v(eGL_VERTEX_BINDING_OFFSET, i, (GLint *)&data->VertexBuffers[i].Offset);
|
||||
gl.glGetIntegeri_v(eGL_VERTEX_BINDING_DIVISOR, i, (GLint *)&data->VertexBuffers[i].Divisor);
|
||||
}
|
||||
|
||||
SetInitialContents(Id, InitialContentData(GLResource(MakeNullResource), 0, (byte *)data));
|
||||
@@ -687,21 +723,24 @@ bool GLResourceManager::Serialise_InitialState(GLResource res)
|
||||
}
|
||||
else if(res.Namespace == eResVertexArray)
|
||||
{
|
||||
VertexArrayInitialData data[16];
|
||||
VAOInitialData data;
|
||||
|
||||
if(m_State >= WRITING)
|
||||
{
|
||||
VertexArrayInitialData *initialdata = (VertexArrayInitialData *)GetInitialContents(Id).blob;
|
||||
memcpy(data, initialdata, sizeof(data));
|
||||
VAOInitialData *initialdata = (VAOInitialData *)GetInitialContents(Id).blob;
|
||||
memcpy(&data, initialdata, sizeof(data));
|
||||
}
|
||||
|
||||
for(GLuint i=0; i < 16; i++)
|
||||
m_pSerialiser->Serialise("data[]", data[i]);
|
||||
{
|
||||
m_pSerialiser->Serialise("VertexAttrib[]", data.VertexAttribs[i]);
|
||||
m_pSerialiser->Serialise("VertexBuffer[]", data.VertexBuffers[i]);
|
||||
}
|
||||
|
||||
if(m_State < WRITING)
|
||||
{
|
||||
byte *blob = Serialiser::AllocAlignedBuffer(sizeof(data));
|
||||
memcpy(blob, data, sizeof(data));
|
||||
memcpy(blob, &data, sizeof(data));
|
||||
|
||||
SetInitialContents(Id, InitialContentData(GLResource(MakeNullResource), 0, blob));
|
||||
}
|
||||
@@ -799,21 +838,30 @@ void GLResourceManager::Apply_InitialState(GLResource live, InitialContentData i
|
||||
|
||||
gl.glBindVertexArray(live.name);
|
||||
|
||||
VertexArrayInitialData *initialdata = (VertexArrayInitialData *)initial.blob;
|
||||
VAOInitialData *initialdata = (VAOInitialData *)initial.blob;
|
||||
|
||||
for(GLuint i=0; i < 16; i++)
|
||||
{
|
||||
if(initialdata[i].enabled)
|
||||
VertexAttribInitialData &attrib = initialdata->VertexAttribs[i];
|
||||
|
||||
if(attrib.enabled)
|
||||
gl.glEnableVertexAttribArray(i);
|
||||
else
|
||||
gl.glDisableVertexAttribArray(i);
|
||||
|
||||
gl.glVertexAttribBinding(i, initialdata[i].vbslot);
|
||||
gl.glVertexAttribBinding(i, attrib.vbslot);
|
||||
|
||||
if(initialdata[i].integer == 0)
|
||||
gl.glVertexAttribFormat(i, initialdata[i].size, initialdata[i].type, (GLboolean)initialdata[i].normalized, initialdata[i].offset);
|
||||
if(initialdata->VertexAttribs[i].integer == 0)
|
||||
gl.glVertexAttribFormat(i, attrib.size, attrib.type, (GLboolean)attrib.normalized, attrib.offset);
|
||||
else
|
||||
gl.glVertexAttribIFormat(i, initialdata[i].size, initialdata[i].type, initialdata[i].offset);
|
||||
gl.glVertexAttribIFormat(i, attrib.size, attrib.type, attrib.offset);
|
||||
|
||||
VertexBufferInitialData &buf = initialdata->VertexBuffers[i];
|
||||
|
||||
GLuint buffer = GetLiveResource(buf.Buffer).name;
|
||||
|
||||
gl.glBindVertexBuffer(i, buffer, (GLintptr)buf.Offset, (GLsizei)buf.Stride);
|
||||
gl.glVertexBindingDivisor(i, buf.Divisor);
|
||||
}
|
||||
|
||||
gl.glBindVertexArray(VAO);
|
||||
|
||||
@@ -95,53 +95,6 @@ void GLRenderState::FetchState()
|
||||
|
||||
m_Real->glGetIntegerv(eGL_VERTEX_ARRAY_BINDING, (GLint *)&VAO);
|
||||
|
||||
static int hackAMDBugVBBinding = -1;
|
||||
|
||||
if(hackAMDBugVBBinding == -1)
|
||||
{
|
||||
GLenum err = m_Real->glGetError();
|
||||
while(err != eGL_NONE) err = m_Real->glGetError();
|
||||
GLint dummy = 0;
|
||||
m_Real->glGetIntegeri_v(eGL_VERTEX_BINDING_BUFFER, 0, &dummy);
|
||||
err = m_Real->glGetError();
|
||||
|
||||
hackAMDBugVBBinding = (err == eGL_NONE ? 0 : 1);
|
||||
|
||||
if(hackAMDBugVBBinding)
|
||||
RDCWARN("Using AMD hack to avoid GL_VERTEX_BINDING_BUFFER");
|
||||
}
|
||||
|
||||
if(VAO != 0)
|
||||
{
|
||||
GLuint hackVAO = 0;
|
||||
if(hackAMDBugVBBinding)
|
||||
{
|
||||
// create 'pass through' VAO so we can use GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING to fetch buffers
|
||||
m_Real->glGenVertexArrays(1, &hackVAO);
|
||||
m_Real->glBindVertexArray(hackVAO);
|
||||
for(GLuint i=0; i < (GLuint)ARRAY_COUNT(VertexBuffers); i++)
|
||||
m_Real->glVertexAttribBinding(i, i);
|
||||
}
|
||||
|
||||
for(GLuint i=0; i < (GLuint)ARRAY_COUNT(VertexBuffers); i++)
|
||||
{
|
||||
if(hackAMDBugVBBinding)
|
||||
m_Real->glGetVertexAttribiv(i, eGL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING, (GLint *)&VertexBuffers[i].Buffer);
|
||||
else
|
||||
m_Real->glGetIntegeri_v(eGL_VERTEX_BINDING_BUFFER, i, (GLint *)&VertexBuffers[i].Buffer);
|
||||
|
||||
m_Real->glGetIntegeri_v(eGL_VERTEX_BINDING_STRIDE, i, (GLint *)&VertexBuffers[i].Stride);
|
||||
m_Real->glGetIntegeri_v(eGL_VERTEX_BINDING_OFFSET, i, (GLint *)&VertexBuffers[i].Offset);
|
||||
m_Real->glGetIntegeri_v(eGL_VERTEX_BINDING_DIVISOR, i, (GLint *)&VertexBuffers[i].Divisor);
|
||||
}
|
||||
|
||||
if(hackAMDBugVBBinding)
|
||||
{
|
||||
m_Real->glBindVertexArray(VAO);
|
||||
m_Real->glDeleteVertexArrays(1, &hackVAO);
|
||||
}
|
||||
}
|
||||
|
||||
// the spec says that you can only query for the format that was previously set, or you get
|
||||
// undefined results. Ie. if someone set ints, this might return anything. However there's also
|
||||
// no way to query for the type so we just have to hope for the best and hope most people are
|
||||
@@ -367,14 +320,6 @@ void GLRenderState::ApplyState()
|
||||
m_Real->glActiveTexture(ActiveTexture);
|
||||
|
||||
m_Real->glBindVertexArray(VAO);
|
||||
if(VAO != 0)
|
||||
{
|
||||
for(GLuint i=0; i < (GLuint)ARRAY_COUNT(VertexBuffers); i++)
|
||||
{
|
||||
m_Real->glBindVertexBuffer(i, VertexBuffers[i].Buffer, (GLintptr)VertexBuffers[i].Offset, (GLsizei)VertexBuffers[i].Stride);
|
||||
m_Real->glVertexBindingDivisor(i, VertexBuffers[i].Divisor);
|
||||
}
|
||||
}
|
||||
|
||||
// See FetchState(). The spec says that you have to SET the right format for the shader too,
|
||||
// but we couldn't query for the format so we can't set it here.
|
||||
@@ -568,7 +513,6 @@ void GLRenderState::Clear()
|
||||
RDCEraseEl(Subroutines);
|
||||
|
||||
RDCEraseEl(VAO);
|
||||
RDCEraseEl(VertexBuffers);
|
||||
|
||||
RDCEraseEl(GenericVertexAttribs);
|
||||
|
||||
@@ -652,16 +596,6 @@ void GLRenderState::Serialise(LogState state, void *ctx, WrappedOpenGL *gl)
|
||||
m_pSerialiser->Serialise("GL_VERTEX_ARRAY_BINDING", ID);
|
||||
if(state < WRITING && ID != ResourceId()) VAO = rm->GetLiveResource(ID).name;
|
||||
}
|
||||
for(size_t i=0; i < ARRAY_COUNT(VertexBuffers); i++)
|
||||
{
|
||||
ResourceId ID = ResourceId();
|
||||
if(state >= WRITING) ID = rm->GetID(BufferRes(ctx, VertexBuffers[i].Buffer));
|
||||
m_pSerialiser->Serialise("GL_VERTEX_BINDING_BUFFER", ID);
|
||||
m_pSerialiser->Serialise("GL_VERTEX_BINDING_DIVISOR", VertexBuffers[i].Divisor);
|
||||
m_pSerialiser->Serialise("GL_VERTEX_BINDING_OFFSET", VertexBuffers[i].Offset);
|
||||
m_pSerialiser->Serialise("GL_VERTEX_BINDING_STRIDE", VertexBuffers[i].Stride);
|
||||
if(state < WRITING && ID != ResourceId()) VertexBuffers[i].Buffer = rm->GetLiveResource(ID).name;
|
||||
}
|
||||
|
||||
for(size_t i=0; i < ARRAY_COUNT(GenericVertexAttribs); i++)
|
||||
{
|
||||
|
||||
@@ -106,13 +106,6 @@ struct GLRenderState
|
||||
eBufIdx_Texture,
|
||||
};
|
||||
|
||||
struct VertexBuffer
|
||||
{
|
||||
GLuint Buffer;
|
||||
uint64_t Stride;
|
||||
uint64_t Offset;
|
||||
uint32_t Divisor;
|
||||
} VertexBuffers[16];
|
||||
GLuint VAO;
|
||||
|
||||
Vec4f GenericVertexAttribs[32];
|
||||
|
||||
@@ -797,11 +797,14 @@ void GLReplay::SavePipelineState()
|
||||
|
||||
for(GLuint i=0; i < (GLuint)numVBufferBindings; i++)
|
||||
{
|
||||
pipe.m_VtxIn.vbuffers[i].Buffer = rm->GetOriginalID(rm->GetID(BufferRes(ctx, rs.VertexBuffers[i].Buffer)));
|
||||
GLuint buffer = GetBoundVertexBuffer(gl.m_Real, i);
|
||||
|
||||
pipe.m_VtxIn.vbuffers[i].Buffer = rm->GetOriginalID(rm->GetID(BufferRes(ctx, buffer)));
|
||||
|
||||
gl.glGetIntegeri_v(eGL_VERTEX_BINDING_STRIDE, i, (GLint *)&pipe.m_VtxIn.vbuffers[i].Stride);
|
||||
gl.glGetIntegeri_v(eGL_VERTEX_BINDING_OFFSET, i, (GLint *)&pipe.m_VtxIn.vbuffers[i].Offset);
|
||||
gl.glGetIntegeri_v(eGL_VERTEX_BINDING_DIVISOR, i, (GLint *)&pipe.m_VtxIn.vbuffers[i].Divisor);
|
||||
|
||||
pipe.m_VtxIn.vbuffers[i].Stride = (uint32_t)rs.VertexBuffers[i].Stride;
|
||||
pipe.m_VtxIn.vbuffers[i].Offset = (uint32_t)rs.VertexBuffers[i].Offset;
|
||||
pipe.m_VtxIn.vbuffers[i].Divisor = rs.VertexBuffers[i].Divisor;
|
||||
pipe.m_VtxIn.vbuffers[i].PerInstance = (pipe.m_VtxIn.vbuffers[i].Divisor != 0);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user