gl_state: Remove VAO cache and tracking
This commit is contained in:
		
							parent
							
								
									2a662fea36
								
							
						
					
					
						commit
						d5ab0358b6
					
				@ -107,7 +107,6 @@ RasterizerOpenGL::RasterizerOpenGL(Core::System& system, Core::Frontend::EmuWind
 | 
			
		||||
    state.draw.shader_program = 0;
 | 
			
		||||
    state.Apply();
 | 
			
		||||
 | 
			
		||||
    LOG_DEBUG(Render_OpenGL, "Sync fixed function OpenGL state here");
 | 
			
		||||
    CheckExtensions();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -121,66 +120,41 @@ void RasterizerOpenGL::CheckExtensions() {
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
GLuint RasterizerOpenGL::SetupVertexFormat() {
 | 
			
		||||
void RasterizerOpenGL::SetupVertexFormat() {
 | 
			
		||||
    auto& gpu = system.GPU().Maxwell3D();
 | 
			
		||||
    const auto& regs = gpu.regs;
 | 
			
		||||
 | 
			
		||||
    MICROPROFILE_SCOPE(OpenGL_VAO);
 | 
			
		||||
 | 
			
		||||
    auto [iter, is_cache_miss] = vertex_array_cache.try_emplace(regs.vertex_attrib_format);
 | 
			
		||||
    auto& vao_entry = iter->second;
 | 
			
		||||
    // Use the vertex array as-is, assumes that the data is formatted correctly for OpenGL. Enables
 | 
			
		||||
    // the first 16 vertex attributes always, as we don't know which ones are actually used until
 | 
			
		||||
    // shader time. Note, Tegra technically supports 32, but we're capping this to 16 for now to
 | 
			
		||||
    // avoid OpenGL errors.
 | 
			
		||||
    // TODO(Subv): Analyze the shader to identify which attributes are actually used and don't
 | 
			
		||||
    // assume every shader uses them all.
 | 
			
		||||
    for (u32 index = 0; index < 16; ++index) {
 | 
			
		||||
        const auto& attrib = regs.vertex_attrib_format[index];
 | 
			
		||||
 | 
			
		||||
    if (is_cache_miss) {
 | 
			
		||||
        vao_entry.Create();
 | 
			
		||||
        const GLuint vao = vao_entry.handle;
 | 
			
		||||
 | 
			
		||||
        // Eventhough we are using DSA to create this vertex array, there is a bug on Intel's blob
 | 
			
		||||
        // that fails to properly create the vertex array if it's not bound even after creating it
 | 
			
		||||
        // with glCreateVertexArrays
 | 
			
		||||
        state.draw.vertex_array = vao;
 | 
			
		||||
        state.ApplyVertexArrayState();
 | 
			
		||||
 | 
			
		||||
        // Use the vertex array as-is, assumes that the data is formatted correctly for OpenGL.
 | 
			
		||||
        // Enables the first 16 vertex attributes always, as we don't know which ones are actually
 | 
			
		||||
        // used until shader time. Note, Tegra technically supports 32, but we're capping this to 16
 | 
			
		||||
        // for now to avoid OpenGL errors.
 | 
			
		||||
        // TODO(Subv): Analyze the shader to identify which attributes are actually used and don't
 | 
			
		||||
        // assume every shader uses them all.
 | 
			
		||||
        for (u32 index = 0; index < 16; ++index) {
 | 
			
		||||
            const auto& attrib = regs.vertex_attrib_format[index];
 | 
			
		||||
 | 
			
		||||
            // Ignore invalid attributes.
 | 
			
		||||
            if (!attrib.IsValid())
 | 
			
		||||
                continue;
 | 
			
		||||
 | 
			
		||||
            const auto& buffer = regs.vertex_array[attrib.buffer];
 | 
			
		||||
            LOG_TRACE(Render_OpenGL,
 | 
			
		||||
                      "vertex attrib {}, count={}, size={}, type={}, offset={}, normalize={}",
 | 
			
		||||
                      index, attrib.ComponentCount(), attrib.SizeString(), attrib.TypeString(),
 | 
			
		||||
                      attrib.offset.Value(), attrib.IsNormalized());
 | 
			
		||||
 | 
			
		||||
            ASSERT(buffer.IsEnabled());
 | 
			
		||||
 | 
			
		||||
            glEnableVertexArrayAttrib(vao, index);
 | 
			
		||||
            if (attrib.type == Tegra::Engines::Maxwell3D::Regs::VertexAttribute::Type::SignedInt ||
 | 
			
		||||
                attrib.type ==
 | 
			
		||||
                    Tegra::Engines::Maxwell3D::Regs::VertexAttribute::Type::UnsignedInt) {
 | 
			
		||||
                glVertexArrayAttribIFormat(vao, index, attrib.ComponentCount(),
 | 
			
		||||
                                           MaxwellToGL::VertexType(attrib), attrib.offset);
 | 
			
		||||
            } else {
 | 
			
		||||
                glVertexArrayAttribFormat(
 | 
			
		||||
                    vao, index, attrib.ComponentCount(), MaxwellToGL::VertexType(attrib),
 | 
			
		||||
                    attrib.IsNormalized() ? GL_TRUE : GL_FALSE, attrib.offset);
 | 
			
		||||
            }
 | 
			
		||||
            glVertexArrayAttribBinding(vao, index, attrib.buffer);
 | 
			
		||||
        // Ignore invalid attributes.
 | 
			
		||||
        if (!attrib.IsValid()) {
 | 
			
		||||
            glDisableVertexAttribArray(index);
 | 
			
		||||
            continue;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
        glEnableVertexAttribArray(index);
 | 
			
		||||
 | 
			
		||||
    state.draw.vertex_array = vao_entry.handle;
 | 
			
		||||
    return vao_entry.handle;
 | 
			
		||||
        if (attrib.type == Maxwell::VertexAttribute::Type::SignedInt ||
 | 
			
		||||
            attrib.type == Maxwell::VertexAttribute::Type::UnsignedInt) {
 | 
			
		||||
            glVertexAttribIFormat(index, attrib.ComponentCount(), MaxwellToGL::VertexType(attrib),
 | 
			
		||||
                                  attrib.offset);
 | 
			
		||||
        } else {
 | 
			
		||||
            glVertexAttribFormat(index, attrib.ComponentCount(), MaxwellToGL::VertexType(attrib),
 | 
			
		||||
                                 attrib.IsNormalized() ? GL_TRUE : GL_FALSE, attrib.offset);
 | 
			
		||||
        }
 | 
			
		||||
        glVertexAttribBinding(index, attrib.buffer);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void RasterizerOpenGL::SetupVertexBuffer(GLuint vao) {
 | 
			
		||||
void RasterizerOpenGL::SetupVertexBuffer() {
 | 
			
		||||
    auto& gpu = system.GPU().Maxwell3D();
 | 
			
		||||
    const auto& regs = gpu.regs;
 | 
			
		||||
 | 
			
		||||
@ -189,8 +163,9 @@ void RasterizerOpenGL::SetupVertexBuffer(GLuint vao) {
 | 
			
		||||
    // Upload all guest vertex arrays sequentially to our buffer
 | 
			
		||||
    for (u32 index = 0; index < Maxwell::NumVertexArrays; ++index) {
 | 
			
		||||
        const auto& vertex_array = regs.vertex_array[index];
 | 
			
		||||
        if (!vertex_array.IsEnabled())
 | 
			
		||||
        if (!vertex_array.IsEnabled()) {
 | 
			
		||||
            continue;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        const GPUVAddr start = vertex_array.StartAddress();
 | 
			
		||||
        const GPUVAddr end = regs.vertex_array_limit[index].LimitAddress();
 | 
			
		||||
@ -205,15 +180,15 @@ void RasterizerOpenGL::SetupVertexBuffer(GLuint vao) {
 | 
			
		||||
 | 
			
		||||
        if (regs.instanced_arrays.IsInstancingEnabled(index) && vertex_array.divisor != 0) {
 | 
			
		||||
            // Enable vertex buffer instancing with the specified divisor.
 | 
			
		||||
            glVertexArrayBindingDivisor(vao, index, vertex_array.divisor);
 | 
			
		||||
            glVertexBindingDivisor(index, vertex_array.divisor);
 | 
			
		||||
        } else {
 | 
			
		||||
            // Disable the vertex buffer instancing.
 | 
			
		||||
            glVertexArrayBindingDivisor(vao, index, 0);
 | 
			
		||||
            glVertexBindingDivisor(index, 0);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void RasterizerOpenGL::SetupVertexInstances(GLuint vao) {
 | 
			
		||||
void RasterizerOpenGL::SetupVertexInstances() {
 | 
			
		||||
    auto& gpu = system.GPU().Maxwell3D();
 | 
			
		||||
    const auto& regs = gpu.regs;
 | 
			
		||||
 | 
			
		||||
@ -222,10 +197,10 @@ void RasterizerOpenGL::SetupVertexInstances(GLuint vao) {
 | 
			
		||||
        if (regs.instanced_arrays.IsInstancingEnabled(index) &&
 | 
			
		||||
            regs.vertex_array[index].divisor != 0) {
 | 
			
		||||
            // Enable vertex buffer instancing with the specified divisor.
 | 
			
		||||
            glVertexArrayBindingDivisor(vao, index, regs.vertex_array[index].divisor);
 | 
			
		||||
            glVertexBindingDivisor(index, regs.vertex_array[index].divisor);
 | 
			
		||||
        } else {
 | 
			
		||||
            // Disable the vertex buffer instancing.
 | 
			
		||||
            glVertexArrayBindingDivisor(vao, index, 0);
 | 
			
		||||
            glVertexBindingDivisor(index, 0);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@ -559,13 +534,12 @@ void RasterizerOpenGL::Draw(bool is_indexed, bool is_instanced) {
 | 
			
		||||
    buffer_cache.Map(buffer_size);
 | 
			
		||||
 | 
			
		||||
    // Prepare vertex array format.
 | 
			
		||||
    const GLuint vao = SetupVertexFormat();
 | 
			
		||||
    vertex_array_pushbuffer.Setup(vao);
 | 
			
		||||
    SetupVertexFormat();
 | 
			
		||||
    vertex_array_pushbuffer.Setup();
 | 
			
		||||
 | 
			
		||||
    // Upload vertex and index data.
 | 
			
		||||
    SetupVertexBuffer(vao);
 | 
			
		||||
    SetupVertexInstances(vao);
 | 
			
		||||
 | 
			
		||||
    SetupVertexBuffer();
 | 
			
		||||
    SetupVertexInstances();
 | 
			
		||||
    GLintptr index_buffer_offset;
 | 
			
		||||
    if (is_indexed) {
 | 
			
		||||
        index_buffer_offset = SetupIndexBuffer();
 | 
			
		||||
 | 
			
		||||
@ -194,11 +194,11 @@ private:
 | 
			
		||||
 | 
			
		||||
    std::size_t CalculateIndexBufferSize() const;
 | 
			
		||||
 | 
			
		||||
    /// Updates and returns a vertex array object representing current vertex format
 | 
			
		||||
    GLuint SetupVertexFormat();
 | 
			
		||||
    /// Updates the current vertex format
 | 
			
		||||
    void SetupVertexFormat();
 | 
			
		||||
 | 
			
		||||
    void SetupVertexBuffer(GLuint vao);
 | 
			
		||||
    void SetupVertexInstances(GLuint vao);
 | 
			
		||||
    void SetupVertexBuffer();
 | 
			
		||||
    void SetupVertexInstances();
 | 
			
		||||
 | 
			
		||||
    GLintptr SetupIndexBuffer();
 | 
			
		||||
 | 
			
		||||
@ -217,10 +217,6 @@ private:
 | 
			
		||||
    ScreenInfo& screen_info;
 | 
			
		||||
 | 
			
		||||
    std::unique_ptr<GLShader::ProgramManager> shader_program_manager;
 | 
			
		||||
    std::map<std::array<Tegra::Engines::Maxwell3D::Regs::VertexAttribute,
 | 
			
		||||
                        Tegra::Engines::Maxwell3D::Regs::NumVertexAttributes>,
 | 
			
		||||
             OGLVertexArray>
 | 
			
		||||
        vertex_array_cache;
 | 
			
		||||
 | 
			
		||||
    static constexpr std::size_t STREAM_BUFFER_SIZE = 128 * 1024 * 1024;
 | 
			
		||||
    OGLBufferCache buffer_cache;
 | 
			
		||||
 | 
			
		||||
@ -189,24 +189,6 @@ void OGLSync::Release() {
 | 
			
		||||
    handle = 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void OGLVertexArray::Create() {
 | 
			
		||||
    if (handle != 0)
 | 
			
		||||
        return;
 | 
			
		||||
 | 
			
		||||
    MICROPROFILE_SCOPE(OpenGL_ResourceCreation);
 | 
			
		||||
    glCreateVertexArrays(1, &handle);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void OGLVertexArray::Release() {
 | 
			
		||||
    if (handle == 0)
 | 
			
		||||
        return;
 | 
			
		||||
 | 
			
		||||
    MICROPROFILE_SCOPE(OpenGL_ResourceDeletion);
 | 
			
		||||
    glDeleteVertexArrays(1, &handle);
 | 
			
		||||
    OpenGLState::GetCurState().ResetVertexArray(handle).Apply();
 | 
			
		||||
    handle = 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void OGLFramebuffer::Create() {
 | 
			
		||||
    if (handle != 0)
 | 
			
		||||
        return;
 | 
			
		||||
 | 
			
		||||
@ -241,31 +241,6 @@ public:
 | 
			
		||||
    GLsync handle = 0;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
class OGLVertexArray : private NonCopyable {
 | 
			
		||||
public:
 | 
			
		||||
    OGLVertexArray() = default;
 | 
			
		||||
 | 
			
		||||
    OGLVertexArray(OGLVertexArray&& o) noexcept : handle(std::exchange(o.handle, 0)) {}
 | 
			
		||||
 | 
			
		||||
    ~OGLVertexArray() {
 | 
			
		||||
        Release();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    OGLVertexArray& operator=(OGLVertexArray&& o) noexcept {
 | 
			
		||||
        Release();
 | 
			
		||||
        handle = std::exchange(o.handle, 0);
 | 
			
		||||
        return *this;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// Creates a new internal OpenGL resource and stores the handle
 | 
			
		||||
    void Create();
 | 
			
		||||
 | 
			
		||||
    /// Deletes the internal OpenGL resource
 | 
			
		||||
    void Release();
 | 
			
		||||
 | 
			
		||||
    GLuint handle = 0;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
class OGLFramebuffer : private NonCopyable {
 | 
			
		||||
public:
 | 
			
		||||
    OGLFramebuffer() = default;
 | 
			
		||||
 | 
			
		||||
@ -98,12 +98,6 @@ void OpenGLState::ApplyFramebufferState() {
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void OpenGLState::ApplyVertexArrayState() {
 | 
			
		||||
    if (UpdateValue(cur_state.draw.vertex_array, draw.vertex_array)) {
 | 
			
		||||
        glBindVertexArray(draw.vertex_array);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void OpenGLState::ApplyShaderProgram() {
 | 
			
		||||
    if (UpdateValue(cur_state.draw.shader_program, draw.shader_program)) {
 | 
			
		||||
        glUseProgram(draw.shader_program);
 | 
			
		||||
@ -338,7 +332,6 @@ void OpenGLState::ApplyImages() {
 | 
			
		||||
void OpenGLState::Apply() {
 | 
			
		||||
    MICROPROFILE_SCOPE(OpenGL_State);
 | 
			
		||||
    ApplyFramebufferState();
 | 
			
		||||
    ApplyVertexArrayState();
 | 
			
		||||
    ApplyShaderProgram();
 | 
			
		||||
    ApplyProgramPipeline();
 | 
			
		||||
    ApplyClipDistances();
 | 
			
		||||
@ -411,13 +404,6 @@ OpenGLState& OpenGLState::ResetPipeline(GLuint handle) {
 | 
			
		||||
    return *this;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
OpenGLState& OpenGLState::ResetVertexArray(GLuint handle) {
 | 
			
		||||
    if (draw.vertex_array == handle) {
 | 
			
		||||
        draw.vertex_array = 0;
 | 
			
		||||
    }
 | 
			
		||||
    return *this;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
OpenGLState& OpenGLState::ResetFramebuffer(GLuint handle) {
 | 
			
		||||
    if (draw.read_framebuffer == handle) {
 | 
			
		||||
        draw.read_framebuffer = 0;
 | 
			
		||||
 | 
			
		||||
@ -74,7 +74,6 @@ public:
 | 
			
		||||
    struct {
 | 
			
		||||
        GLuint read_framebuffer = 0; // GL_READ_FRAMEBUFFER_BINDING
 | 
			
		||||
        GLuint draw_framebuffer = 0; // GL_DRAW_FRAMEBUFFER_BINDING
 | 
			
		||||
        GLuint vertex_array = 0;     // GL_VERTEX_ARRAY_BINDING
 | 
			
		||||
        GLuint shader_program = 0;   // GL_CURRENT_PROGRAM
 | 
			
		||||
        GLuint program_pipeline = 0; // GL_PROGRAM_PIPELINE_BINDING
 | 
			
		||||
    } draw;
 | 
			
		||||
@ -117,7 +116,6 @@ public:
 | 
			
		||||
    void Apply();
 | 
			
		||||
 | 
			
		||||
    void ApplyFramebufferState();
 | 
			
		||||
    void ApplyVertexArrayState();
 | 
			
		||||
    void ApplyShaderProgram();
 | 
			
		||||
    void ApplyProgramPipeline();
 | 
			
		||||
    void ApplyClipDistances();
 | 
			
		||||
@ -142,7 +140,6 @@ public:
 | 
			
		||||
    OpenGLState& ResetSampler(GLuint handle);
 | 
			
		||||
    OpenGLState& ResetProgram(GLuint handle);
 | 
			
		||||
    OpenGLState& ResetPipeline(GLuint handle);
 | 
			
		||||
    OpenGLState& ResetVertexArray(GLuint handle);
 | 
			
		||||
    OpenGLState& ResetFramebuffer(GLuint handle);
 | 
			
		||||
    OpenGLState& ResetRenderbuffer(GLuint handle);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -441,22 +441,8 @@ void RendererOpenGL::InitOpenGLObjects() {
 | 
			
		||||
    // Generate VBO handle for drawing
 | 
			
		||||
    vertex_buffer.Create();
 | 
			
		||||
 | 
			
		||||
    // Generate VAO
 | 
			
		||||
    vertex_array.Create();
 | 
			
		||||
    state.draw.vertex_array = vertex_array.handle;
 | 
			
		||||
 | 
			
		||||
    // Attach vertex data to VAO
 | 
			
		||||
    glNamedBufferData(vertex_buffer.handle, sizeof(ScreenRectVertex) * 4, nullptr, GL_STREAM_DRAW);
 | 
			
		||||
    glVertexArrayAttribFormat(vertex_array.handle, PositionLocation, 2, GL_FLOAT, GL_FALSE,
 | 
			
		||||
                              offsetof(ScreenRectVertex, position));
 | 
			
		||||
    glVertexArrayAttribFormat(vertex_array.handle, TexCoordLocation, 2, GL_FLOAT, GL_FALSE,
 | 
			
		||||
                              offsetof(ScreenRectVertex, tex_coord));
 | 
			
		||||
    glVertexArrayAttribBinding(vertex_array.handle, PositionLocation, 0);
 | 
			
		||||
    glVertexArrayAttribBinding(vertex_array.handle, TexCoordLocation, 0);
 | 
			
		||||
    glEnableVertexArrayAttrib(vertex_array.handle, PositionLocation);
 | 
			
		||||
    glEnableVertexArrayAttrib(vertex_array.handle, TexCoordLocation);
 | 
			
		||||
    glVertexArrayVertexBuffer(vertex_array.handle, 0, vertex_buffer.handle, 0,
 | 
			
		||||
                              sizeof(ScreenRectVertex));
 | 
			
		||||
 | 
			
		||||
    // Allocate textures for the screen
 | 
			
		||||
    screen_info.texture.resource.Create(GL_TEXTURE_2D);
 | 
			
		||||
@ -581,6 +567,14 @@ void RendererOpenGL::DrawScreenTriangles(const ScreenInfo& screen_info, float x,
 | 
			
		||||
    glCullFace(GL_BACK);
 | 
			
		||||
    glFrontFace(GL_CW);
 | 
			
		||||
 | 
			
		||||
    glVertexAttribFormat(PositionLocation, 2, GL_FLOAT, GL_FALSE,
 | 
			
		||||
                         offsetof(ScreenRectVertex, position));
 | 
			
		||||
    glVertexAttribFormat(TexCoordLocation, 2, GL_FLOAT, GL_FALSE,
 | 
			
		||||
                         offsetof(ScreenRectVertex, tex_coord));
 | 
			
		||||
    glVertexAttribBinding(PositionLocation, 0);
 | 
			
		||||
    glVertexAttribBinding(TexCoordLocation, 0);
 | 
			
		||||
    glBindVertexBuffer(0, vertex_buffer.handle, 0, sizeof(ScreenRectVertex));
 | 
			
		||||
 | 
			
		||||
    glNamedBufferSubData(vertex_buffer.handle, 0, sizeof(vertices), std::data(vertices));
 | 
			
		||||
    glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
 | 
			
		||||
    // Restore default state
 | 
			
		||||
 | 
			
		||||
@ -96,7 +96,6 @@ private:
 | 
			
		||||
    OpenGLState state;
 | 
			
		||||
 | 
			
		||||
    // OpenGL object IDs
 | 
			
		||||
    OGLVertexArray vertex_array;
 | 
			
		||||
    OGLBuffer vertex_buffer;
 | 
			
		||||
    OGLProgram shader;
 | 
			
		||||
    OGLFramebuffer screenshot_framebuffer;
 | 
			
		||||
 | 
			
		||||
@ -24,8 +24,7 @@ VertexArrayPushBuffer::VertexArrayPushBuffer() = default;
 | 
			
		||||
 | 
			
		||||
VertexArrayPushBuffer::~VertexArrayPushBuffer() = default;
 | 
			
		||||
 | 
			
		||||
void VertexArrayPushBuffer::Setup(GLuint vao_) {
 | 
			
		||||
    vao = vao_;
 | 
			
		||||
void VertexArrayPushBuffer::Setup() {
 | 
			
		||||
    index_buffer = nullptr;
 | 
			
		||||
    vertex_buffers.clear();
 | 
			
		||||
}
 | 
			
		||||
@ -41,13 +40,12 @@ void VertexArrayPushBuffer::SetVertexBuffer(GLuint binding_index, const GLuint*
 | 
			
		||||
 | 
			
		||||
void VertexArrayPushBuffer::Bind() {
 | 
			
		||||
    if (index_buffer) {
 | 
			
		||||
        glVertexArrayElementBuffer(vao, *index_buffer);
 | 
			
		||||
        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, *index_buffer);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // TODO(Rodrigo): Find a way to ARB_multi_bind this
 | 
			
		||||
    for (const auto& entry : vertex_buffers) {
 | 
			
		||||
        glVertexArrayVertexBuffer(vao, entry.binding_index, *entry.buffer, entry.offset,
 | 
			
		||||
                                  entry.stride);
 | 
			
		||||
        glBindVertexBuffer(entry.binding_index, *entry.buffer, entry.offset, entry.stride);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -16,7 +16,7 @@ public:
 | 
			
		||||
    explicit VertexArrayPushBuffer();
 | 
			
		||||
    ~VertexArrayPushBuffer();
 | 
			
		||||
 | 
			
		||||
    void Setup(GLuint vao_);
 | 
			
		||||
    void Setup();
 | 
			
		||||
 | 
			
		||||
    void SetIndexBuffer(const GLuint* buffer);
 | 
			
		||||
 | 
			
		||||
@ -28,7 +28,6 @@ public:
 | 
			
		||||
private:
 | 
			
		||||
    struct Entry;
 | 
			
		||||
 | 
			
		||||
    GLuint vao{};
 | 
			
		||||
    const GLuint* index_buffer{};
 | 
			
		||||
    std::vector<Entry> vertex_buffers;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
		Loading…
	
		Reference in New Issue
	
	Block a user