diff --git a/src/video_core/renderer_opengl/gl_rasterizer.cpp b/src/video_core/renderer_opengl/gl_rasterizer.cpp index acdae849c..9658d379c 100644 --- a/src/video_core/renderer_opengl/gl_rasterizer.cpp +++ b/src/video_core/renderer_opengl/gl_rasterizer.cpp @@ -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(); diff --git a/src/video_core/renderer_opengl/gl_rasterizer.h b/src/video_core/renderer_opengl/gl_rasterizer.h index 8afc3c205..b97f9f518 100644 --- a/src/video_core/renderer_opengl/gl_rasterizer.h +++ b/src/video_core/renderer_opengl/gl_rasterizer.h @@ -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 shader_program_manager; - std::map, - OGLVertexArray> - vertex_array_cache; static constexpr std::size_t STREAM_BUFFER_SIZE = 128 * 1024 * 1024; OGLBufferCache buffer_cache; diff --git a/src/video_core/renderer_opengl/gl_resource_manager.cpp b/src/video_core/renderer_opengl/gl_resource_manager.cpp index c0aee770f..00355c1da 100644 --- a/src/video_core/renderer_opengl/gl_resource_manager.cpp +++ b/src/video_core/renderer_opengl/gl_resource_manager.cpp @@ -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; diff --git a/src/video_core/renderer_opengl/gl_resource_manager.h b/src/video_core/renderer_opengl/gl_resource_manager.h index 995a4e45e..de93f4212 100644 --- a/src/video_core/renderer_opengl/gl_resource_manager.h +++ b/src/video_core/renderer_opengl/gl_resource_manager.h @@ -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; diff --git a/src/video_core/renderer_opengl/gl_state.cpp b/src/video_core/renderer_opengl/gl_state.cpp index 6b5eea342..1c39e7fba 100644 --- a/src/video_core/renderer_opengl/gl_state.cpp +++ b/src/video_core/renderer_opengl/gl_state.cpp @@ -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; diff --git a/src/video_core/renderer_opengl/gl_state.h b/src/video_core/renderer_opengl/gl_state.h index 366753714..f7c722b36 100644 --- a/src/video_core/renderer_opengl/gl_state.h +++ b/src/video_core/renderer_opengl/gl_state.h @@ -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); diff --git a/src/video_core/renderer_opengl/renderer_opengl.cpp b/src/video_core/renderer_opengl/renderer_opengl.cpp index 9cd67e05e..2fb5938e2 100644 --- a/src/video_core/renderer_opengl/renderer_opengl.cpp +++ b/src/video_core/renderer_opengl/renderer_opengl.cpp @@ -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 diff --git a/src/video_core/renderer_opengl/renderer_opengl.h b/src/video_core/renderer_opengl/renderer_opengl.h index d45e69cbc..978a4d0eb 100644 --- a/src/video_core/renderer_opengl/renderer_opengl.h +++ b/src/video_core/renderer_opengl/renderer_opengl.h @@ -96,7 +96,6 @@ private: OpenGLState state; // OpenGL object IDs - OGLVertexArray vertex_array; OGLBuffer vertex_buffer; OGLProgram shader; OGLFramebuffer screenshot_framebuffer; diff --git a/src/video_core/renderer_opengl/utils.cpp b/src/video_core/renderer_opengl/utils.cpp index ac99e6385..f2aaf06db 100644 --- a/src/video_core/renderer_opengl/utils.cpp +++ b/src/video_core/renderer_opengl/utils.cpp @@ -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); } } diff --git a/src/video_core/renderer_opengl/utils.h b/src/video_core/renderer_opengl/utils.h index 3ad7c02d4..e8612a9ec 100644 --- a/src/video_core/renderer_opengl/utils.h +++ b/src/video_core/renderer_opengl/utils.h @@ -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 vertex_buffers; };