gl_rasterizer: Use DSA for vertex array objects
This commit is contained in:
		| @@ -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(); | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 ReinUsesLisp
					ReinUsesLisp