gl_rasterizer: Use DSA for vertex array objects
This commit is contained in:
		
							parent
							
								
									ea4928393f
								
							
						
					
					
						commit
						35c095898b
					
				@ -135,27 +135,25 @@ void RasterizerOpenGL::CheckExtensions() {
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void RasterizerOpenGL::SetupVertexFormat() {
 | 
			
		||||
GLuint RasterizerOpenGL::SetupVertexFormat() {
 | 
			
		||||
    auto& gpu = Core::System::GetInstance().GPU().Maxwell3D();
 | 
			
		||||
    const auto& regs = gpu.regs;
 | 
			
		||||
 | 
			
		||||
    if (!gpu.dirty_flags.vertex_attrib_format)
 | 
			
		||||
        return;
 | 
			
		||||
    if (!gpu.dirty_flags.vertex_attrib_format) {
 | 
			
		||||
        return state.draw.vertex_array;
 | 
			
		||||
    }
 | 
			
		||||
    gpu.dirty_flags.vertex_attrib_format = false;
 | 
			
		||||
 | 
			
		||||
    MICROPROFILE_SCOPE(OpenGL_VAO);
 | 
			
		||||
 | 
			
		||||
    auto [iter, is_cache_miss] = vertex_array_cache.try_emplace(regs.vertex_attrib_format);
 | 
			
		||||
    auto& VAO = iter->second;
 | 
			
		||||
    auto& vao_entry = iter->second;
 | 
			
		||||
 | 
			
		||||
    if (is_cache_miss) {
 | 
			
		||||
        VAO.Create();
 | 
			
		||||
        state.draw.vertex_array = VAO.handle;
 | 
			
		||||
        state.ApplyVertexBufferState();
 | 
			
		||||
        vao_entry.Create();
 | 
			
		||||
        const GLuint vao = vao_entry.handle;
 | 
			
		||||
 | 
			
		||||
        // The index buffer binding is stored within the VAO. Stupid OpenGL, but easy to work
 | 
			
		||||
        // around.
 | 
			
		||||
        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, buffer_cache.GetHandle());
 | 
			
		||||
        glVertexArrayElementBuffer(vao, buffer_cache.GetHandle());
 | 
			
		||||
 | 
			
		||||
        // 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
 | 
			
		||||
@ -163,7 +161,7 @@ void RasterizerOpenGL::SetupVertexFormat() {
 | 
			
		||||
        // 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 (unsigned index = 0; index < 16; ++index) {
 | 
			
		||||
        for (u32 index = 0; index < 16; ++index) {
 | 
			
		||||
            const auto& attrib = regs.vertex_attrib_format[index];
 | 
			
		||||
 | 
			
		||||
            // Ignore invalid attributes.
 | 
			
		||||
@ -178,28 +176,29 @@ void RasterizerOpenGL::SetupVertexFormat() {
 | 
			
		||||
 | 
			
		||||
            ASSERT(buffer.IsEnabled());
 | 
			
		||||
 | 
			
		||||
            glEnableVertexAttribArray(index);
 | 
			
		||||
            glEnableVertexArrayAttrib(vao, index);
 | 
			
		||||
            if (attrib.type == Tegra::Engines::Maxwell3D::Regs::VertexAttribute::Type::SignedInt ||
 | 
			
		||||
                attrib.type ==
 | 
			
		||||
                    Tegra::Engines::Maxwell3D::Regs::VertexAttribute::Type::UnsignedInt) {
 | 
			
		||||
                glVertexAttribIFormat(index, attrib.ComponentCount(),
 | 
			
		||||
                                      MaxwellToGL::VertexType(attrib), attrib.offset);
 | 
			
		||||
                glVertexArrayAttribIFormat(vao, index, attrib.ComponentCount(),
 | 
			
		||||
                                           MaxwellToGL::VertexType(attrib), attrib.offset);
 | 
			
		||||
            } else {
 | 
			
		||||
                glVertexAttribFormat(index, attrib.ComponentCount(),
 | 
			
		||||
                                     MaxwellToGL::VertexType(attrib),
 | 
			
		||||
                                     attrib.IsNormalized() ? GL_TRUE : GL_FALSE, attrib.offset);
 | 
			
		||||
                glVertexArrayAttribFormat(
 | 
			
		||||
                    vao, index, attrib.ComponentCount(), MaxwellToGL::VertexType(attrib),
 | 
			
		||||
                    attrib.IsNormalized() ? GL_TRUE : GL_FALSE, attrib.offset);
 | 
			
		||||
            }
 | 
			
		||||
            glVertexAttribBinding(index, attrib.buffer);
 | 
			
		||||
            glVertexArrayAttribBinding(vao, index, attrib.buffer);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    state.draw.vertex_array = VAO.handle;
 | 
			
		||||
    state.ApplyVertexBufferState();
 | 
			
		||||
 | 
			
		||||
    // Rebinding the VAO invalidates the vertex buffer bindings.
 | 
			
		||||
    gpu.dirty_flags.vertex_array = 0xFFFFFFFF;
 | 
			
		||||
 | 
			
		||||
    state.draw.vertex_array = vao_entry.handle;
 | 
			
		||||
    return vao_entry.handle;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void RasterizerOpenGL::SetupVertexBuffer() {
 | 
			
		||||
void RasterizerOpenGL::SetupVertexBuffer(GLuint vao) {
 | 
			
		||||
    auto& gpu = Core::System::GetInstance().GPU().Maxwell3D();
 | 
			
		||||
    const auto& regs = gpu.regs;
 | 
			
		||||
 | 
			
		||||
@ -217,7 +216,7 @@ void RasterizerOpenGL::SetupVertexBuffer() {
 | 
			
		||||
        if (!vertex_array.IsEnabled())
 | 
			
		||||
            continue;
 | 
			
		||||
 | 
			
		||||
        Tegra::GPUVAddr start = vertex_array.StartAddress();
 | 
			
		||||
        const Tegra::GPUVAddr start = vertex_array.StartAddress();
 | 
			
		||||
        const Tegra::GPUVAddr end = regs.vertex_array_limit[index].LimitAddress();
 | 
			
		||||
 | 
			
		||||
        ASSERT(end > start);
 | 
			
		||||
@ -225,21 +224,18 @@ void RasterizerOpenGL::SetupVertexBuffer() {
 | 
			
		||||
        const GLintptr vertex_buffer_offset = buffer_cache.UploadMemory(start, size);
 | 
			
		||||
 | 
			
		||||
        // Bind the vertex array to the buffer at the current offset.
 | 
			
		||||
        glBindVertexBuffer(index, buffer_cache.GetHandle(), vertex_buffer_offset,
 | 
			
		||||
                           vertex_array.stride);
 | 
			
		||||
        glVertexArrayVertexBuffer(vao, index, buffer_cache.GetHandle(), vertex_buffer_offset,
 | 
			
		||||
                                  vertex_array.stride);
 | 
			
		||||
 | 
			
		||||
        if (regs.instanced_arrays.IsInstancingEnabled(index) && vertex_array.divisor != 0) {
 | 
			
		||||
            // Enable vertex buffer instancing with the specified divisor.
 | 
			
		||||
            glVertexBindingDivisor(index, vertex_array.divisor);
 | 
			
		||||
            glVertexArrayBindingDivisor(vao, index, vertex_array.divisor);
 | 
			
		||||
        } else {
 | 
			
		||||
            // Disable the vertex buffer instancing.
 | 
			
		||||
            glVertexBindingDivisor(index, 0);
 | 
			
		||||
            glVertexArrayBindingDivisor(vao, index, 0);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Implicit set by glBindVertexBuffer. Stupid glstate handling...
 | 
			
		||||
    state.draw.vertex_buffer = buffer_cache.GetHandle();
 | 
			
		||||
 | 
			
		||||
    gpu.dirty_flags.vertex_array = 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -689,9 +685,6 @@ void RasterizerOpenGL::DrawArrays() {
 | 
			
		||||
    // Draw the vertex batch
 | 
			
		||||
    const bool is_indexed = accelerate_draw == AccelDraw::Indexed;
 | 
			
		||||
 | 
			
		||||
    state.draw.vertex_buffer = buffer_cache.GetHandle();
 | 
			
		||||
    state.ApplyVertexBufferState();
 | 
			
		||||
 | 
			
		||||
    std::size_t buffer_size = CalculateVertexArraysSize();
 | 
			
		||||
 | 
			
		||||
    // Add space for index buffer (keeping in mind non-core primitives)
 | 
			
		||||
@ -721,8 +714,9 @@ void RasterizerOpenGL::DrawArrays() {
 | 
			
		||||
        gpu.dirty_flags.vertex_array = 0xFFFFFFFF;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    SetupVertexFormat();
 | 
			
		||||
    SetupVertexBuffer();
 | 
			
		||||
    const GLuint vao = SetupVertexFormat();
 | 
			
		||||
    SetupVertexBuffer(vao);
 | 
			
		||||
 | 
			
		||||
    DrawParameters params = SetupDraw();
 | 
			
		||||
    SetupShaders(params.primitive_mode);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -209,8 +209,10 @@ private:
 | 
			
		||||
 | 
			
		||||
    std::size_t CalculateIndexBufferSize() const;
 | 
			
		||||
 | 
			
		||||
    void SetupVertexFormat();
 | 
			
		||||
    void SetupVertexBuffer();
 | 
			
		||||
    /// Updates and returns a vertex array object representing current vertex format
 | 
			
		||||
    GLuint SetupVertexFormat();
 | 
			
		||||
 | 
			
		||||
    void SetupVertexBuffer(GLuint vao);
 | 
			
		||||
 | 
			
		||||
    DrawParameters SetupDraw();
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -117,7 +117,7 @@ void OGLBuffer::Create() {
 | 
			
		||||
        return;
 | 
			
		||||
 | 
			
		||||
    MICROPROFILE_SCOPE(OpenGL_ResourceCreation);
 | 
			
		||||
    glGenBuffers(1, &handle);
 | 
			
		||||
    glCreateBuffers(1, &handle);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void OGLBuffer::Release() {
 | 
			
		||||
@ -126,7 +126,6 @@ void OGLBuffer::Release() {
 | 
			
		||||
 | 
			
		||||
    MICROPROFILE_SCOPE(OpenGL_ResourceDeletion);
 | 
			
		||||
    glDeleteBuffers(1, &handle);
 | 
			
		||||
    OpenGLState::GetCurState().ResetBuffer(handle).Apply();
 | 
			
		||||
    handle = 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -152,7 +151,7 @@ void OGLVertexArray::Create() {
 | 
			
		||||
        return;
 | 
			
		||||
 | 
			
		||||
    MICROPROFILE_SCOPE(OpenGL_ResourceCreation);
 | 
			
		||||
    glGenVertexArrays(1, &handle);
 | 
			
		||||
    glCreateVertexArrays(1, &handle);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void OGLVertexArray::Release() {
 | 
			
		||||
 | 
			
		||||
@ -83,7 +83,6 @@ OpenGLState::OpenGLState() {
 | 
			
		||||
    draw.read_framebuffer = 0;
 | 
			
		||||
    draw.draw_framebuffer = 0;
 | 
			
		||||
    draw.vertex_array = 0;
 | 
			
		||||
    draw.vertex_buffer = 0;
 | 
			
		||||
    draw.shader_program = 0;
 | 
			
		||||
    draw.program_pipeline = 0;
 | 
			
		||||
 | 
			
		||||
@ -513,18 +512,6 @@ void OpenGLState::ApplyFramebufferState() const {
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void OpenGLState::ApplyVertexBufferState() const {
 | 
			
		||||
    // Vertex array
 | 
			
		||||
    if (draw.vertex_array != cur_state.draw.vertex_array) {
 | 
			
		||||
        glBindVertexArray(draw.vertex_array);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Vertex buffer
 | 
			
		||||
    if (draw.vertex_buffer != cur_state.draw.vertex_buffer) {
 | 
			
		||||
        glBindBuffer(GL_ARRAY_BUFFER, draw.vertex_buffer);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void OpenGLState::ApplyDepthClamp() const {
 | 
			
		||||
    if (depth_clamp.far_plane == cur_state.depth_clamp.far_plane &&
 | 
			
		||||
        depth_clamp.near_plane == cur_state.depth_clamp.near_plane) {
 | 
			
		||||
@ -542,7 +529,11 @@ void OpenGLState::ApplyDepthClamp() const {
 | 
			
		||||
 | 
			
		||||
void OpenGLState::Apply() const {
 | 
			
		||||
    ApplyFramebufferState();
 | 
			
		||||
    ApplyVertexBufferState();
 | 
			
		||||
 | 
			
		||||
    // Vertex array
 | 
			
		||||
    if (draw.vertex_array != cur_state.draw.vertex_array) {
 | 
			
		||||
        glBindVertexArray(draw.vertex_array);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Shader program
 | 
			
		||||
    if (draw.shader_program != cur_state.draw.shader_program) {
 | 
			
		||||
@ -633,13 +624,6 @@ OpenGLState& OpenGLState::ResetPipeline(GLuint handle) {
 | 
			
		||||
    return *this;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
OpenGLState& OpenGLState::ResetBuffer(GLuint handle) {
 | 
			
		||||
    if (draw.vertex_buffer == handle) {
 | 
			
		||||
        draw.vertex_buffer = 0;
 | 
			
		||||
    }
 | 
			
		||||
    return *this;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
OpenGLState& OpenGLState::ResetVertexArray(GLuint handle) {
 | 
			
		||||
    if (draw.vertex_array == handle) {
 | 
			
		||||
        draw.vertex_array = 0;
 | 
			
		||||
 | 
			
		||||
@ -154,7 +154,6 @@ public:
 | 
			
		||||
        GLuint read_framebuffer; // GL_READ_FRAMEBUFFER_BINDING
 | 
			
		||||
        GLuint draw_framebuffer; // GL_DRAW_FRAMEBUFFER_BINDING
 | 
			
		||||
        GLuint vertex_array;     // GL_VERTEX_ARRAY_BINDING
 | 
			
		||||
        GLuint vertex_buffer;    // GL_ARRAY_BUFFER_BINDING
 | 
			
		||||
        GLuint shader_program;   // GL_CURRENT_PROGRAM
 | 
			
		||||
        GLuint program_pipeline; // GL_PROGRAM_PIPELINE_BINDING
 | 
			
		||||
    } draw;
 | 
			
		||||
@ -207,8 +206,6 @@ public:
 | 
			
		||||
    void Apply() const;
 | 
			
		||||
    /// Apply only the state afecting the framebuffer
 | 
			
		||||
    void ApplyFramebufferState() const;
 | 
			
		||||
    /// Apply only the state afecting the vertex buffer
 | 
			
		||||
    void ApplyVertexBufferState() const;
 | 
			
		||||
    /// Set the initial OpenGL state
 | 
			
		||||
    static void ApplyDefaultState();
 | 
			
		||||
    /// Resets any references to the given resource
 | 
			
		||||
@ -216,7 +213,6 @@ public:
 | 
			
		||||
    OpenGLState& ResetSampler(GLuint handle);
 | 
			
		||||
    OpenGLState& ResetProgram(GLuint handle);
 | 
			
		||||
    OpenGLState& ResetPipeline(GLuint handle);
 | 
			
		||||
    OpenGLState& ResetBuffer(GLuint handle);
 | 
			
		||||
    OpenGLState& ResetVertexArray(GLuint handle);
 | 
			
		||||
    OpenGLState& ResetFramebuffer(GLuint handle);
 | 
			
		||||
    void EmulateViewportWithScissor();
 | 
			
		||||
 | 
			
		||||
@ -245,19 +245,20 @@ void RendererOpenGL::InitOpenGLObjects() {
 | 
			
		||||
 | 
			
		||||
    // Generate VAO
 | 
			
		||||
    vertex_array.Create();
 | 
			
		||||
 | 
			
		||||
    state.draw.vertex_array = vertex_array.handle;
 | 
			
		||||
    state.draw.vertex_buffer = vertex_buffer.handle;
 | 
			
		||||
    state.Apply();
 | 
			
		||||
 | 
			
		||||
    // Attach vertex data to VAO
 | 
			
		||||
    glBufferData(GL_ARRAY_BUFFER, sizeof(ScreenRectVertex) * 4, nullptr, GL_STREAM_DRAW);
 | 
			
		||||
    glVertexAttribPointer(attrib_position, 2, GL_FLOAT, GL_FALSE, sizeof(ScreenRectVertex),
 | 
			
		||||
                          (GLvoid*)offsetof(ScreenRectVertex, position));
 | 
			
		||||
    glVertexAttribPointer(attrib_tex_coord, 2, GL_FLOAT, GL_FALSE, sizeof(ScreenRectVertex),
 | 
			
		||||
                          (GLvoid*)offsetof(ScreenRectVertex, tex_coord));
 | 
			
		||||
    glEnableVertexAttribArray(attrib_position);
 | 
			
		||||
    glEnableVertexAttribArray(attrib_tex_coord);
 | 
			
		||||
    glNamedBufferData(vertex_buffer.handle, sizeof(ScreenRectVertex) * 4, nullptr, GL_STREAM_DRAW);
 | 
			
		||||
    glVertexArrayAttribFormat(vertex_array.handle, attrib_position, 2, GL_FLOAT, GL_FALSE,
 | 
			
		||||
                              offsetof(ScreenRectVertex, position));
 | 
			
		||||
    glVertexArrayAttribFormat(vertex_array.handle, attrib_tex_coord, 2, GL_FLOAT, GL_FALSE,
 | 
			
		||||
                              offsetof(ScreenRectVertex, tex_coord));
 | 
			
		||||
    glVertexArrayAttribBinding(vertex_array.handle, attrib_position, 0);
 | 
			
		||||
    glVertexArrayAttribBinding(vertex_array.handle, attrib_tex_coord, 0);
 | 
			
		||||
    glEnableVertexArrayAttrib(vertex_array.handle, attrib_position);
 | 
			
		||||
    glEnableVertexArrayAttrib(vertex_array.handle, attrib_tex_coord);
 | 
			
		||||
    glVertexArrayVertexBuffer(vertex_array.handle, 0, vertex_buffer.handle, 0,
 | 
			
		||||
                              sizeof(ScreenRectVertex));
 | 
			
		||||
 | 
			
		||||
    // Allocate textures for the screen
 | 
			
		||||
    screen_info.texture.resource.Create();
 | 
			
		||||
@ -369,14 +370,12 @@ void RendererOpenGL::DrawScreenTriangles(const ScreenInfo& screen_info, float x,
 | 
			
		||||
    state.texture_units[0].texture = screen_info.display_texture;
 | 
			
		||||
    state.texture_units[0].swizzle = {GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA};
 | 
			
		||||
    // Workaround brigthness problems in SMO by enabling sRGB in the final output
 | 
			
		||||
    // if it has been used in the frame
 | 
			
		||||
    // Needed because of this bug in QT
 | 
			
		||||
    // QTBUG-50987
 | 
			
		||||
    // if it has been used in the frame. Needed because of this bug in QT: QTBUG-50987
 | 
			
		||||
    state.framebuffer_srgb.enabled = OpenGLState::GetsRGBUsed();
 | 
			
		||||
    state.Apply();
 | 
			
		||||
    glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(vertices), vertices.data());
 | 
			
		||||
    glNamedBufferSubData(vertex_buffer.handle, 0, sizeof(vertices), vertices.data());
 | 
			
		||||
    glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
 | 
			
		||||
    // restore default state
 | 
			
		||||
    // Restore default state
 | 
			
		||||
    state.framebuffer_srgb.enabled = false;
 | 
			
		||||
    state.texture_units[0].texture = 0;
 | 
			
		||||
    state.Apply();
 | 
			
		||||
 | 
			
		||||
		Loading…
	
		Reference in New Issue
	
	Block a user