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