diff options
| author | 2019-01-20 14:06:01 -0500 | |
|---|---|---|
| committer | 2019-01-20 14:06:01 -0500 | |
| commit | cbf8bea9d570d0207b7bc8d63b73109f2df059d5 (patch) | |
| tree | 93ae5db4c12f0c90ef84a7da8fa199c36ba43cb8 /src | |
| parent | Merge pull request #2032 from lioncash/web (diff) | |
| parent | gl_rasterizer: Workaround Intel VAO DSA bug (diff) | |
| download | yuzu-cbf8bea9d570d0207b7bc8d63b73109f2df059d5.tar.gz yuzu-cbf8bea9d570d0207b7bc8d63b73109f2df059d5.tar.xz yuzu-cbf8bea9d570d0207b7bc8d63b73109f2df059d5.zip | |
Merge pull request #2002 from ReinUsesLisp/dsa-vao-buffer
gl_rasterizer: Use DSA for VAOs and buffers
Diffstat (limited to 'src')
| -rw-r--r-- | src/video_core/renderer_opengl/gl_buffer_cache.cpp | 2 | ||||
| -rw-r--r-- | src/video_core/renderer_opengl/gl_rasterizer.cpp | 68 | ||||
| -rw-r--r-- | src/video_core/renderer_opengl/gl_rasterizer.h | 6 | ||||
| -rw-r--r-- | src/video_core/renderer_opengl/gl_resource_manager.cpp | 5 | ||||
| -rw-r--r-- | src/video_core/renderer_opengl/gl_state.cpp | 27 | ||||
| -rw-r--r-- | src/video_core/renderer_opengl/gl_state.h | 9 | ||||
| -rw-r--r-- | src/video_core/renderer_opengl/gl_stream_buffer.cpp | 26 | ||||
| -rw-r--r-- | src/video_core/renderer_opengl/gl_stream_buffer.h | 3 | ||||
| -rw-r--r-- | src/video_core/renderer_opengl/renderer_opengl.cpp | 30 |
9 files changed, 73 insertions, 103 deletions
diff --git a/src/video_core/renderer_opengl/gl_buffer_cache.cpp b/src/video_core/renderer_opengl/gl_buffer_cache.cpp index 46a6c0308..bd2b30e77 100644 --- a/src/video_core/renderer_opengl/gl_buffer_cache.cpp +++ b/src/video_core/renderer_opengl/gl_buffer_cache.cpp | |||
| @@ -14,7 +14,7 @@ | |||
| 14 | namespace OpenGL { | 14 | namespace OpenGL { |
| 15 | 15 | ||
| 16 | OGLBufferCache::OGLBufferCache(RasterizerOpenGL& rasterizer, std::size_t size) | 16 | OGLBufferCache::OGLBufferCache(RasterizerOpenGL& rasterizer, std::size_t size) |
| 17 | : RasterizerCache{rasterizer}, stream_buffer(GL_ARRAY_BUFFER, size) {} | 17 | : RasterizerCache{rasterizer}, stream_buffer(size, true) {} |
| 18 | 18 | ||
| 19 | GLintptr OGLBufferCache::UploadMemory(Tegra::GPUVAddr gpu_addr, std::size_t size, | 19 | GLintptr OGLBufferCache::UploadMemory(Tegra::GPUVAddr gpu_addr, std::size_t size, |
| 20 | std::size_t alignment, bool cache) { | 20 | std::size_t alignment, bool cache) { |
diff --git a/src/video_core/renderer_opengl/gl_rasterizer.cpp b/src/video_core/renderer_opengl/gl_rasterizer.cpp index 27d259f51..0c2a3265b 100644 --- a/src/video_core/renderer_opengl/gl_rasterizer.cpp +++ b/src/video_core/renderer_opengl/gl_rasterizer.cpp | |||
| @@ -135,27 +135,31 @@ void RasterizerOpenGL::CheckExtensions() { | |||
| 135 | } | 135 | } |
| 136 | } | 136 | } |
| 137 | 137 | ||
| 138 | void RasterizerOpenGL::SetupVertexFormat() { | 138 | GLuint RasterizerOpenGL::SetupVertexFormat() { |
| 139 | auto& gpu = Core::System::GetInstance().GPU().Maxwell3D(); | 139 | auto& gpu = Core::System::GetInstance().GPU().Maxwell3D(); |
| 140 | const auto& regs = gpu.regs; | 140 | const auto& regs = gpu.regs; |
| 141 | 141 | ||
| 142 | if (!gpu.dirty_flags.vertex_attrib_format) | 142 | if (!gpu.dirty_flags.vertex_attrib_format) { |
| 143 | return; | 143 | return state.draw.vertex_array; |
| 144 | } | ||
| 144 | gpu.dirty_flags.vertex_attrib_format = false; | 145 | gpu.dirty_flags.vertex_attrib_format = false; |
| 145 | 146 | ||
| 146 | MICROPROFILE_SCOPE(OpenGL_VAO); | 147 | MICROPROFILE_SCOPE(OpenGL_VAO); |
| 147 | 148 | ||
| 148 | auto [iter, is_cache_miss] = vertex_array_cache.try_emplace(regs.vertex_attrib_format); | 149 | auto [iter, is_cache_miss] = vertex_array_cache.try_emplace(regs.vertex_attrib_format); |
| 149 | auto& VAO = iter->second; | 150 | auto& vao_entry = iter->second; |
| 150 | 151 | ||
| 151 | if (is_cache_miss) { | 152 | if (is_cache_miss) { |
| 152 | VAO.Create(); | 153 | vao_entry.Create(); |
| 153 | state.draw.vertex_array = VAO.handle; | 154 | const GLuint vao = vao_entry.handle; |
| 154 | state.ApplyVertexBufferState(); | ||
| 155 | 155 | ||
| 156 | // The index buffer binding is stored within the VAO. Stupid OpenGL, but easy to work | 156 | // Eventhough we are using DSA to create this vertex array, there is a bug on Intel's blob |
| 157 | // around. | 157 | // that fails to properly create the vertex array if it's not bound even after creating it |
| 158 | glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, buffer_cache.GetHandle()); | 158 | // with glCreateVertexArrays |
| 159 | state.draw.vertex_array = vao; | ||
| 160 | state.ApplyVertexArrayState(); | ||
| 161 | |||
| 162 | glVertexArrayElementBuffer(vao, buffer_cache.GetHandle()); | ||
| 159 | 163 | ||
| 160 | // Use the vertex array as-is, assumes that the data is formatted correctly for OpenGL. | 164 | // Use the vertex array as-is, assumes that the data is formatted correctly for OpenGL. |
| 161 | // Enables the first 16 vertex attributes always, as we don't know which ones are actually | 165 | // Enables the first 16 vertex attributes always, as we don't know which ones are actually |
| @@ -163,7 +167,7 @@ void RasterizerOpenGL::SetupVertexFormat() { | |||
| 163 | // for now to avoid OpenGL errors. | 167 | // for now to avoid OpenGL errors. |
| 164 | // TODO(Subv): Analyze the shader to identify which attributes are actually used and don't | 168 | // TODO(Subv): Analyze the shader to identify which attributes are actually used and don't |
| 165 | // assume every shader uses them all. | 169 | // assume every shader uses them all. |
| 166 | for (unsigned index = 0; index < 16; ++index) { | 170 | for (u32 index = 0; index < 16; ++index) { |
| 167 | const auto& attrib = regs.vertex_attrib_format[index]; | 171 | const auto& attrib = regs.vertex_attrib_format[index]; |
| 168 | 172 | ||
| 169 | // Ignore invalid attributes. | 173 | // Ignore invalid attributes. |
| @@ -178,28 +182,29 @@ void RasterizerOpenGL::SetupVertexFormat() { | |||
| 178 | 182 | ||
| 179 | ASSERT(buffer.IsEnabled()); | 183 | ASSERT(buffer.IsEnabled()); |
| 180 | 184 | ||
| 181 | glEnableVertexAttribArray(index); | 185 | glEnableVertexArrayAttrib(vao, index); |
| 182 | if (attrib.type == Tegra::Engines::Maxwell3D::Regs::VertexAttribute::Type::SignedInt || | 186 | if (attrib.type == Tegra::Engines::Maxwell3D::Regs::VertexAttribute::Type::SignedInt || |
| 183 | attrib.type == | 187 | attrib.type == |
| 184 | Tegra::Engines::Maxwell3D::Regs::VertexAttribute::Type::UnsignedInt) { | 188 | Tegra::Engines::Maxwell3D::Regs::VertexAttribute::Type::UnsignedInt) { |
| 185 | glVertexAttribIFormat(index, attrib.ComponentCount(), | 189 | glVertexArrayAttribIFormat(vao, index, attrib.ComponentCount(), |
| 186 | MaxwellToGL::VertexType(attrib), attrib.offset); | 190 | MaxwellToGL::VertexType(attrib), attrib.offset); |
| 187 | } else { | 191 | } else { |
| 188 | glVertexAttribFormat(index, attrib.ComponentCount(), | 192 | glVertexArrayAttribFormat( |
| 189 | MaxwellToGL::VertexType(attrib), | 193 | vao, index, attrib.ComponentCount(), MaxwellToGL::VertexType(attrib), |
| 190 | attrib.IsNormalized() ? GL_TRUE : GL_FALSE, attrib.offset); | 194 | attrib.IsNormalized() ? GL_TRUE : GL_FALSE, attrib.offset); |
| 191 | } | 195 | } |
| 192 | glVertexAttribBinding(index, attrib.buffer); | 196 | glVertexArrayAttribBinding(vao, index, attrib.buffer); |
| 193 | } | 197 | } |
| 194 | } | 198 | } |
| 195 | state.draw.vertex_array = VAO.handle; | ||
| 196 | state.ApplyVertexBufferState(); | ||
| 197 | 199 | ||
| 198 | // Rebinding the VAO invalidates the vertex buffer bindings. | 200 | // Rebinding the VAO invalidates the vertex buffer bindings. |
| 199 | gpu.dirty_flags.vertex_array = 0xFFFFFFFF; | 201 | gpu.dirty_flags.vertex_array = 0xFFFFFFFF; |
| 202 | |||
| 203 | state.draw.vertex_array = vao_entry.handle; | ||
| 204 | return vao_entry.handle; | ||
| 200 | } | 205 | } |
| 201 | 206 | ||
| 202 | void RasterizerOpenGL::SetupVertexBuffer() { | 207 | void RasterizerOpenGL::SetupVertexBuffer(GLuint vao) { |
| 203 | auto& gpu = Core::System::GetInstance().GPU().Maxwell3D(); | 208 | auto& gpu = Core::System::GetInstance().GPU().Maxwell3D(); |
| 204 | const auto& regs = gpu.regs; | 209 | const auto& regs = gpu.regs; |
| 205 | 210 | ||
| @@ -217,7 +222,7 @@ void RasterizerOpenGL::SetupVertexBuffer() { | |||
| 217 | if (!vertex_array.IsEnabled()) | 222 | if (!vertex_array.IsEnabled()) |
| 218 | continue; | 223 | continue; |
| 219 | 224 | ||
| 220 | Tegra::GPUVAddr start = vertex_array.StartAddress(); | 225 | const Tegra::GPUVAddr start = vertex_array.StartAddress(); |
| 221 | const Tegra::GPUVAddr end = regs.vertex_array_limit[index].LimitAddress(); | 226 | const Tegra::GPUVAddr end = regs.vertex_array_limit[index].LimitAddress(); |
| 222 | 227 | ||
| 223 | ASSERT(end > start); | 228 | ASSERT(end > start); |
| @@ -225,21 +230,18 @@ void RasterizerOpenGL::SetupVertexBuffer() { | |||
| 225 | const GLintptr vertex_buffer_offset = buffer_cache.UploadMemory(start, size); | 230 | const GLintptr vertex_buffer_offset = buffer_cache.UploadMemory(start, size); |
| 226 | 231 | ||
| 227 | // Bind the vertex array to the buffer at the current offset. | 232 | // Bind the vertex array to the buffer at the current offset. |
| 228 | glBindVertexBuffer(index, buffer_cache.GetHandle(), vertex_buffer_offset, | 233 | glVertexArrayVertexBuffer(vao, index, buffer_cache.GetHandle(), vertex_buffer_offset, |
| 229 | vertex_array.stride); | 234 | vertex_array.stride); |
| 230 | 235 | ||
| 231 | if (regs.instanced_arrays.IsInstancingEnabled(index) && vertex_array.divisor != 0) { | 236 | if (regs.instanced_arrays.IsInstancingEnabled(index) && vertex_array.divisor != 0) { |
| 232 | // Enable vertex buffer instancing with the specified divisor. | 237 | // Enable vertex buffer instancing with the specified divisor. |
| 233 | glVertexBindingDivisor(index, vertex_array.divisor); | 238 | glVertexArrayBindingDivisor(vao, index, vertex_array.divisor); |
| 234 | } else { | 239 | } else { |
| 235 | // Disable the vertex buffer instancing. | 240 | // Disable the vertex buffer instancing. |
| 236 | glVertexBindingDivisor(index, 0); | 241 | glVertexArrayBindingDivisor(vao, index, 0); |
| 237 | } | 242 | } |
| 238 | } | 243 | } |
| 239 | 244 | ||
| 240 | // Implicit set by glBindVertexBuffer. Stupid glstate handling... | ||
| 241 | state.draw.vertex_buffer = buffer_cache.GetHandle(); | ||
| 242 | |||
| 243 | gpu.dirty_flags.vertex_array = 0; | 245 | gpu.dirty_flags.vertex_array = 0; |
| 244 | } | 246 | } |
| 245 | 247 | ||
| @@ -691,9 +693,6 @@ void RasterizerOpenGL::DrawArrays() { | |||
| 691 | // Draw the vertex batch | 693 | // Draw the vertex batch |
| 692 | const bool is_indexed = accelerate_draw == AccelDraw::Indexed; | 694 | const bool is_indexed = accelerate_draw == AccelDraw::Indexed; |
| 693 | 695 | ||
| 694 | state.draw.vertex_buffer = buffer_cache.GetHandle(); | ||
| 695 | state.ApplyVertexBufferState(); | ||
| 696 | |||
| 697 | std::size_t buffer_size = CalculateVertexArraysSize(); | 696 | std::size_t buffer_size = CalculateVertexArraysSize(); |
| 698 | 697 | ||
| 699 | // Add space for index buffer (keeping in mind non-core primitives) | 698 | // Add space for index buffer (keeping in mind non-core primitives) |
| @@ -723,8 +722,9 @@ void RasterizerOpenGL::DrawArrays() { | |||
| 723 | gpu.dirty_flags.vertex_array = 0xFFFFFFFF; | 722 | gpu.dirty_flags.vertex_array = 0xFFFFFFFF; |
| 724 | } | 723 | } |
| 725 | 724 | ||
| 726 | SetupVertexFormat(); | 725 | const GLuint vao = SetupVertexFormat(); |
| 727 | SetupVertexBuffer(); | 726 | SetupVertexBuffer(vao); |
| 727 | |||
| 728 | DrawParameters params = SetupDraw(); | 728 | DrawParameters params = SetupDraw(); |
| 729 | SetupShaders(params.primitive_mode); | 729 | SetupShaders(params.primitive_mode); |
| 730 | 730 | ||
diff --git a/src/video_core/renderer_opengl/gl_rasterizer.h b/src/video_core/renderer_opengl/gl_rasterizer.h index a53edee6d..fe230083f 100644 --- a/src/video_core/renderer_opengl/gl_rasterizer.h +++ b/src/video_core/renderer_opengl/gl_rasterizer.h | |||
| @@ -215,8 +215,10 @@ private: | |||
| 215 | 215 | ||
| 216 | std::size_t CalculateIndexBufferSize() const; | 216 | std::size_t CalculateIndexBufferSize() const; |
| 217 | 217 | ||
| 218 | void SetupVertexFormat(); | 218 | /// Updates and returns a vertex array object representing current vertex format |
| 219 | void SetupVertexBuffer(); | 219 | GLuint SetupVertexFormat(); |
| 220 | |||
| 221 | void SetupVertexBuffer(GLuint vao); | ||
| 220 | 222 | ||
| 221 | DrawParameters SetupDraw(); | 223 | DrawParameters SetupDraw(); |
| 222 | 224 | ||
diff --git a/src/video_core/renderer_opengl/gl_resource_manager.cpp b/src/video_core/renderer_opengl/gl_resource_manager.cpp index c17d5ac00..1da744158 100644 --- a/src/video_core/renderer_opengl/gl_resource_manager.cpp +++ b/src/video_core/renderer_opengl/gl_resource_manager.cpp | |||
| @@ -117,7 +117,7 @@ void OGLBuffer::Create() { | |||
| 117 | return; | 117 | return; |
| 118 | 118 | ||
| 119 | MICROPROFILE_SCOPE(OpenGL_ResourceCreation); | 119 | MICROPROFILE_SCOPE(OpenGL_ResourceCreation); |
| 120 | glGenBuffers(1, &handle); | 120 | glCreateBuffers(1, &handle); |
| 121 | } | 121 | } |
| 122 | 122 | ||
| 123 | void OGLBuffer::Release() { | 123 | void OGLBuffer::Release() { |
| @@ -126,7 +126,6 @@ void OGLBuffer::Release() { | |||
| 126 | 126 | ||
| 127 | MICROPROFILE_SCOPE(OpenGL_ResourceDeletion); | 127 | MICROPROFILE_SCOPE(OpenGL_ResourceDeletion); |
| 128 | glDeleteBuffers(1, &handle); | 128 | glDeleteBuffers(1, &handle); |
| 129 | OpenGLState::GetCurState().ResetBuffer(handle).Apply(); | ||
| 130 | handle = 0; | 129 | handle = 0; |
| 131 | } | 130 | } |
| 132 | 131 | ||
| @@ -152,7 +151,7 @@ void OGLVertexArray::Create() { | |||
| 152 | return; | 151 | return; |
| 153 | 152 | ||
| 154 | MICROPROFILE_SCOPE(OpenGL_ResourceCreation); | 153 | MICROPROFILE_SCOPE(OpenGL_ResourceCreation); |
| 155 | glGenVertexArrays(1, &handle); | 154 | glCreateVertexArrays(1, &handle); |
| 156 | } | 155 | } |
| 157 | 156 | ||
| 158 | void OGLVertexArray::Release() { | 157 | void OGLVertexArray::Release() { |
diff --git a/src/video_core/renderer_opengl/gl_state.cpp b/src/video_core/renderer_opengl/gl_state.cpp index dc0a5ed5e..b7ba59350 100644 --- a/src/video_core/renderer_opengl/gl_state.cpp +++ b/src/video_core/renderer_opengl/gl_state.cpp | |||
| @@ -83,8 +83,6 @@ OpenGLState::OpenGLState() { | |||
| 83 | draw.read_framebuffer = 0; | 83 | draw.read_framebuffer = 0; |
| 84 | draw.draw_framebuffer = 0; | 84 | draw.draw_framebuffer = 0; |
| 85 | draw.vertex_array = 0; | 85 | draw.vertex_array = 0; |
| 86 | draw.vertex_buffer = 0; | ||
| 87 | draw.uniform_buffer = 0; | ||
| 88 | draw.shader_program = 0; | 86 | draw.shader_program = 0; |
| 89 | draw.program_pipeline = 0; | 87 | draw.program_pipeline = 0; |
| 90 | 88 | ||
| @@ -505,7 +503,6 @@ void OpenGLState::ApplySamplers() const { | |||
| 505 | } | 503 | } |
| 506 | 504 | ||
| 507 | void OpenGLState::ApplyFramebufferState() const { | 505 | void OpenGLState::ApplyFramebufferState() const { |
| 508 | // Framebuffer | ||
| 509 | if (draw.read_framebuffer != cur_state.draw.read_framebuffer) { | 506 | if (draw.read_framebuffer != cur_state.draw.read_framebuffer) { |
| 510 | glBindFramebuffer(GL_READ_FRAMEBUFFER, draw.read_framebuffer); | 507 | glBindFramebuffer(GL_READ_FRAMEBUFFER, draw.read_framebuffer); |
| 511 | } | 508 | } |
| @@ -514,16 +511,10 @@ void OpenGLState::ApplyFramebufferState() const { | |||
| 514 | } | 511 | } |
| 515 | } | 512 | } |
| 516 | 513 | ||
| 517 | void OpenGLState::ApplyVertexBufferState() const { | 514 | void OpenGLState::ApplyVertexArrayState() const { |
| 518 | // Vertex array | ||
| 519 | if (draw.vertex_array != cur_state.draw.vertex_array) { | 515 | if (draw.vertex_array != cur_state.draw.vertex_array) { |
| 520 | glBindVertexArray(draw.vertex_array); | 516 | glBindVertexArray(draw.vertex_array); |
| 521 | } | 517 | } |
| 522 | |||
| 523 | // Vertex buffer | ||
| 524 | if (draw.vertex_buffer != cur_state.draw.vertex_buffer) { | ||
| 525 | glBindBuffer(GL_ARRAY_BUFFER, draw.vertex_buffer); | ||
| 526 | } | ||
| 527 | } | 518 | } |
| 528 | 519 | ||
| 529 | void OpenGLState::ApplyDepthClamp() const { | 520 | void OpenGLState::ApplyDepthClamp() const { |
| @@ -543,11 +534,7 @@ void OpenGLState::ApplyDepthClamp() const { | |||
| 543 | 534 | ||
| 544 | void OpenGLState::Apply() const { | 535 | void OpenGLState::Apply() const { |
| 545 | ApplyFramebufferState(); | 536 | ApplyFramebufferState(); |
| 546 | ApplyVertexBufferState(); | 537 | ApplyVertexArrayState(); |
| 547 | // Uniform buffer | ||
| 548 | if (draw.uniform_buffer != cur_state.draw.uniform_buffer) { | ||
| 549 | glBindBuffer(GL_UNIFORM_BUFFER, draw.uniform_buffer); | ||
| 550 | } | ||
| 551 | 538 | ||
| 552 | // Shader program | 539 | // Shader program |
| 553 | if (draw.shader_program != cur_state.draw.shader_program) { | 540 | if (draw.shader_program != cur_state.draw.shader_program) { |
| @@ -638,16 +625,6 @@ OpenGLState& OpenGLState::ResetPipeline(GLuint handle) { | |||
| 638 | return *this; | 625 | return *this; |
| 639 | } | 626 | } |
| 640 | 627 | ||
| 641 | OpenGLState& OpenGLState::ResetBuffer(GLuint handle) { | ||
| 642 | if (draw.vertex_buffer == handle) { | ||
| 643 | draw.vertex_buffer = 0; | ||
| 644 | } | ||
| 645 | if (draw.uniform_buffer == handle) { | ||
| 646 | draw.uniform_buffer = 0; | ||
| 647 | } | ||
| 648 | return *this; | ||
| 649 | } | ||
| 650 | |||
| 651 | OpenGLState& OpenGLState::ResetVertexArray(GLuint handle) { | 628 | OpenGLState& OpenGLState::ResetVertexArray(GLuint handle) { |
| 652 | if (draw.vertex_array == handle) { | 629 | if (draw.vertex_array == handle) { |
| 653 | draw.vertex_array = 0; | 630 | draw.vertex_array = 0; |
diff --git a/src/video_core/renderer_opengl/gl_state.h b/src/video_core/renderer_opengl/gl_state.h index 439bfbc98..a5a7c0920 100644 --- a/src/video_core/renderer_opengl/gl_state.h +++ b/src/video_core/renderer_opengl/gl_state.h | |||
| @@ -154,8 +154,6 @@ public: | |||
| 154 | GLuint read_framebuffer; // GL_READ_FRAMEBUFFER_BINDING | 154 | GLuint read_framebuffer; // GL_READ_FRAMEBUFFER_BINDING |
| 155 | GLuint draw_framebuffer; // GL_DRAW_FRAMEBUFFER_BINDING | 155 | GLuint draw_framebuffer; // GL_DRAW_FRAMEBUFFER_BINDING |
| 156 | GLuint vertex_array; // GL_VERTEX_ARRAY_BINDING | 156 | GLuint vertex_array; // GL_VERTEX_ARRAY_BINDING |
| 157 | GLuint vertex_buffer; // GL_ARRAY_BUFFER_BINDING | ||
| 158 | GLuint uniform_buffer; // GL_UNIFORM_BUFFER_BINDING | ||
| 159 | GLuint shader_program; // GL_CURRENT_PROGRAM | 157 | GLuint shader_program; // GL_CURRENT_PROGRAM |
| 160 | GLuint program_pipeline; // GL_PROGRAM_PIPELINE_BINDING | 158 | GLuint program_pipeline; // GL_PROGRAM_PIPELINE_BINDING |
| 161 | } draw; | 159 | } draw; |
| @@ -206,10 +204,10 @@ public: | |||
| 206 | } | 204 | } |
| 207 | /// Apply this state as the current OpenGL state | 205 | /// Apply this state as the current OpenGL state |
| 208 | void Apply() const; | 206 | void Apply() const; |
| 209 | /// Apply only the state afecting the framebuffer | 207 | /// Apply only the state affecting the framebuffer |
| 210 | void ApplyFramebufferState() const; | 208 | void ApplyFramebufferState() const; |
| 211 | /// Apply only the state afecting the vertex buffer | 209 | /// Apply only the state affecting the vertex array |
| 212 | void ApplyVertexBufferState() const; | 210 | void ApplyVertexArrayState() const; |
| 213 | /// Set the initial OpenGL state | 211 | /// Set the initial OpenGL state |
| 214 | static void ApplyDefaultState(); | 212 | static void ApplyDefaultState(); |
| 215 | /// Resets any references to the given resource | 213 | /// Resets any references to the given resource |
| @@ -217,7 +215,6 @@ public: | |||
| 217 | OpenGLState& ResetSampler(GLuint handle); | 215 | OpenGLState& ResetSampler(GLuint handle); |
| 218 | OpenGLState& ResetProgram(GLuint handle); | 216 | OpenGLState& ResetProgram(GLuint handle); |
| 219 | OpenGLState& ResetPipeline(GLuint handle); | 217 | OpenGLState& ResetPipeline(GLuint handle); |
| 220 | OpenGLState& ResetBuffer(GLuint handle); | ||
| 221 | OpenGLState& ResetVertexArray(GLuint handle); | 218 | OpenGLState& ResetVertexArray(GLuint handle); |
| 222 | OpenGLState& ResetFramebuffer(GLuint handle); | 219 | OpenGLState& ResetFramebuffer(GLuint handle); |
| 223 | void EmulateViewportWithScissor(); | 220 | void EmulateViewportWithScissor(); |
diff --git a/src/video_core/renderer_opengl/gl_stream_buffer.cpp b/src/video_core/renderer_opengl/gl_stream_buffer.cpp index b97b895a4..d0b14b3f6 100644 --- a/src/video_core/renderer_opengl/gl_stream_buffer.cpp +++ b/src/video_core/renderer_opengl/gl_stream_buffer.cpp | |||
| @@ -15,13 +15,12 @@ MICROPROFILE_DEFINE(OpenGL_StreamBuffer, "OpenGL", "Stream Buffer Orphaning", | |||
| 15 | 15 | ||
| 16 | namespace OpenGL { | 16 | namespace OpenGL { |
| 17 | 17 | ||
| 18 | OGLStreamBuffer::OGLStreamBuffer(GLenum target, GLsizeiptr size, bool prefer_coherent) | 18 | OGLStreamBuffer::OGLStreamBuffer(GLsizeiptr size, bool vertex_data_usage, bool prefer_coherent) |
| 19 | : gl_target(target), buffer_size(size) { | 19 | : buffer_size(size) { |
| 20 | gl_buffer.Create(); | 20 | gl_buffer.Create(); |
| 21 | glBindBuffer(gl_target, gl_buffer.handle); | ||
| 22 | 21 | ||
| 23 | GLsizeiptr allocate_size = size; | 22 | GLsizeiptr allocate_size = size; |
| 24 | if (target == GL_ARRAY_BUFFER) { | 23 | if (vertex_data_usage) { |
| 25 | // On AMD GPU there is a strange crash in indexed drawing. The crash happens when the buffer | 24 | // On AMD GPU there is a strange crash in indexed drawing. The crash happens when the buffer |
| 26 | // read position is near the end and is an out-of-bound access to the vertex buffer. This is | 25 | // read position is near the end and is an out-of-bound access to the vertex buffer. This is |
| 27 | // probably a bug in the driver and is related to the usage of vec3<byte> attributes in the | 26 | // probably a bug in the driver and is related to the usage of vec3<byte> attributes in the |
| @@ -35,18 +34,17 @@ OGLStreamBuffer::OGLStreamBuffer(GLenum target, GLsizeiptr size, bool prefer_coh | |||
| 35 | coherent = prefer_coherent; | 34 | coherent = prefer_coherent; |
| 36 | const GLbitfield flags = | 35 | const GLbitfield flags = |
| 37 | GL_MAP_WRITE_BIT | GL_MAP_PERSISTENT_BIT | (coherent ? GL_MAP_COHERENT_BIT : 0); | 36 | GL_MAP_WRITE_BIT | GL_MAP_PERSISTENT_BIT | (coherent ? GL_MAP_COHERENT_BIT : 0); |
| 38 | glBufferStorage(gl_target, allocate_size, nullptr, flags); | 37 | glNamedBufferStorage(gl_buffer.handle, allocate_size, nullptr, flags); |
| 39 | mapped_ptr = static_cast<u8*>(glMapBufferRange( | 38 | mapped_ptr = static_cast<u8*>(glMapNamedBufferRange( |
| 40 | gl_target, 0, buffer_size, flags | (coherent ? 0 : GL_MAP_FLUSH_EXPLICIT_BIT))); | 39 | gl_buffer.handle, 0, buffer_size, flags | (coherent ? 0 : GL_MAP_FLUSH_EXPLICIT_BIT))); |
| 41 | } else { | 40 | } else { |
| 42 | glBufferData(gl_target, allocate_size, nullptr, GL_STREAM_DRAW); | 41 | glNamedBufferData(gl_buffer.handle, allocate_size, nullptr, GL_STREAM_DRAW); |
| 43 | } | 42 | } |
| 44 | } | 43 | } |
| 45 | 44 | ||
| 46 | OGLStreamBuffer::~OGLStreamBuffer() { | 45 | OGLStreamBuffer::~OGLStreamBuffer() { |
| 47 | if (persistent) { | 46 | if (persistent) { |
| 48 | glBindBuffer(gl_target, gl_buffer.handle); | 47 | glUnmapNamedBuffer(gl_buffer.handle); |
| 49 | glUnmapBuffer(gl_target); | ||
| 50 | } | 48 | } |
| 51 | gl_buffer.Release(); | 49 | gl_buffer.Release(); |
| 52 | } | 50 | } |
| @@ -74,7 +72,7 @@ std::tuple<u8*, GLintptr, bool> OGLStreamBuffer::Map(GLsizeiptr size, GLintptr a | |||
| 74 | invalidate = true; | 72 | invalidate = true; |
| 75 | 73 | ||
| 76 | if (persistent) { | 74 | if (persistent) { |
| 77 | glUnmapBuffer(gl_target); | 75 | glUnmapNamedBuffer(gl_buffer.handle); |
| 78 | } | 76 | } |
| 79 | } | 77 | } |
| 80 | 78 | ||
| @@ -84,7 +82,7 @@ std::tuple<u8*, GLintptr, bool> OGLStreamBuffer::Map(GLsizeiptr size, GLintptr a | |||
| 84 | (coherent ? GL_MAP_COHERENT_BIT : GL_MAP_FLUSH_EXPLICIT_BIT) | | 82 | (coherent ? GL_MAP_COHERENT_BIT : GL_MAP_FLUSH_EXPLICIT_BIT) | |
| 85 | (invalidate ? GL_MAP_INVALIDATE_BUFFER_BIT : GL_MAP_UNSYNCHRONIZED_BIT); | 83 | (invalidate ? GL_MAP_INVALIDATE_BUFFER_BIT : GL_MAP_UNSYNCHRONIZED_BIT); |
| 86 | mapped_ptr = static_cast<u8*>( | 84 | mapped_ptr = static_cast<u8*>( |
| 87 | glMapBufferRange(gl_target, buffer_pos, buffer_size - buffer_pos, flags)); | 85 | glMapNamedBufferRange(gl_buffer.handle, buffer_pos, buffer_size - buffer_pos, flags)); |
| 88 | mapped_offset = buffer_pos; | 86 | mapped_offset = buffer_pos; |
| 89 | } | 87 | } |
| 90 | 88 | ||
| @@ -95,11 +93,11 @@ void OGLStreamBuffer::Unmap(GLsizeiptr size) { | |||
| 95 | ASSERT(size <= mapped_size); | 93 | ASSERT(size <= mapped_size); |
| 96 | 94 | ||
| 97 | if (!coherent && size > 0) { | 95 | if (!coherent && size > 0) { |
| 98 | glFlushMappedBufferRange(gl_target, buffer_pos - mapped_offset, size); | 96 | glFlushMappedNamedBufferRange(gl_buffer.handle, buffer_pos - mapped_offset, size); |
| 99 | } | 97 | } |
| 100 | 98 | ||
| 101 | if (!persistent) { | 99 | if (!persistent) { |
| 102 | glUnmapBuffer(gl_target); | 100 | glUnmapNamedBuffer(gl_buffer.handle); |
| 103 | } | 101 | } |
| 104 | 102 | ||
| 105 | buffer_pos += size; | 103 | buffer_pos += size; |
diff --git a/src/video_core/renderer_opengl/gl_stream_buffer.h b/src/video_core/renderer_opengl/gl_stream_buffer.h index ae7961bd7..3d18ecb4d 100644 --- a/src/video_core/renderer_opengl/gl_stream_buffer.h +++ b/src/video_core/renderer_opengl/gl_stream_buffer.h | |||
| @@ -13,7 +13,7 @@ namespace OpenGL { | |||
| 13 | 13 | ||
| 14 | class OGLStreamBuffer : private NonCopyable { | 14 | class OGLStreamBuffer : private NonCopyable { |
| 15 | public: | 15 | public: |
| 16 | explicit OGLStreamBuffer(GLenum target, GLsizeiptr size, bool prefer_coherent = false); | 16 | explicit OGLStreamBuffer(GLsizeiptr size, bool vertex_data_usage, bool prefer_coherent = false); |
| 17 | ~OGLStreamBuffer(); | 17 | ~OGLStreamBuffer(); |
| 18 | 18 | ||
| 19 | GLuint GetHandle() const; | 19 | GLuint GetHandle() const; |
| @@ -33,7 +33,6 @@ public: | |||
| 33 | 33 | ||
| 34 | private: | 34 | private: |
| 35 | OGLBuffer gl_buffer; | 35 | OGLBuffer gl_buffer; |
| 36 | GLenum gl_target; | ||
| 37 | 36 | ||
| 38 | bool coherent = false; | 37 | bool coherent = false; |
| 39 | bool persistent = false; | 38 | bool persistent = false; |
diff --git a/src/video_core/renderer_opengl/renderer_opengl.cpp b/src/video_core/renderer_opengl/renderer_opengl.cpp index 235732d86..c268c9686 100644 --- a/src/video_core/renderer_opengl/renderer_opengl.cpp +++ b/src/video_core/renderer_opengl/renderer_opengl.cpp | |||
| @@ -245,20 +245,20 @@ void RendererOpenGL::InitOpenGLObjects() { | |||
| 245 | 245 | ||
| 246 | // Generate VAO | 246 | // Generate VAO |
| 247 | vertex_array.Create(); | 247 | vertex_array.Create(); |
| 248 | |||
| 249 | state.draw.vertex_array = vertex_array.handle; | 248 | state.draw.vertex_array = vertex_array.handle; |
| 250 | state.draw.vertex_buffer = vertex_buffer.handle; | ||
| 251 | state.draw.uniform_buffer = 0; | ||
| 252 | state.Apply(); | ||
| 253 | 249 | ||
| 254 | // Attach vertex data to VAO | 250 | // Attach vertex data to VAO |
| 255 | glBufferData(GL_ARRAY_BUFFER, sizeof(ScreenRectVertex) * 4, nullptr, GL_STREAM_DRAW); | 251 | glNamedBufferData(vertex_buffer.handle, sizeof(ScreenRectVertex) * 4, nullptr, GL_STREAM_DRAW); |
| 256 | glVertexAttribPointer(attrib_position, 2, GL_FLOAT, GL_FALSE, sizeof(ScreenRectVertex), | 252 | glVertexArrayAttribFormat(vertex_array.handle, attrib_position, 2, GL_FLOAT, GL_FALSE, |
| 257 | (GLvoid*)offsetof(ScreenRectVertex, position)); | 253 | offsetof(ScreenRectVertex, position)); |
| 258 | glVertexAttribPointer(attrib_tex_coord, 2, GL_FLOAT, GL_FALSE, sizeof(ScreenRectVertex), | 254 | glVertexArrayAttribFormat(vertex_array.handle, attrib_tex_coord, 2, GL_FLOAT, GL_FALSE, |
| 259 | (GLvoid*)offsetof(ScreenRectVertex, tex_coord)); | 255 | offsetof(ScreenRectVertex, tex_coord)); |
| 260 | glEnableVertexAttribArray(attrib_position); | 256 | glVertexArrayAttribBinding(vertex_array.handle, attrib_position, 0); |
| 261 | glEnableVertexAttribArray(attrib_tex_coord); | 257 | glVertexArrayAttribBinding(vertex_array.handle, attrib_tex_coord, 0); |
| 258 | glEnableVertexArrayAttrib(vertex_array.handle, attrib_position); | ||
| 259 | glEnableVertexArrayAttrib(vertex_array.handle, attrib_tex_coord); | ||
| 260 | glVertexArrayVertexBuffer(vertex_array.handle, 0, vertex_buffer.handle, 0, | ||
| 261 | sizeof(ScreenRectVertex)); | ||
| 262 | 262 | ||
| 263 | // Allocate textures for the screen | 263 | // Allocate textures for the screen |
| 264 | screen_info.texture.resource.Create(); | 264 | screen_info.texture.resource.Create(); |
| @@ -370,14 +370,12 @@ void RendererOpenGL::DrawScreenTriangles(const ScreenInfo& screen_info, float x, | |||
| 370 | state.texture_units[0].texture = screen_info.display_texture; | 370 | state.texture_units[0].texture = screen_info.display_texture; |
| 371 | state.texture_units[0].swizzle = {GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA}; | 371 | state.texture_units[0].swizzle = {GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA}; |
| 372 | // Workaround brigthness problems in SMO by enabling sRGB in the final output | 372 | // Workaround brigthness problems in SMO by enabling sRGB in the final output |
| 373 | // if it has been used in the frame | 373 | // if it has been used in the frame. Needed because of this bug in QT: QTBUG-50987 |
| 374 | // Needed because of this bug in QT | ||
| 375 | // QTBUG-50987 | ||
| 376 | state.framebuffer_srgb.enabled = OpenGLState::GetsRGBUsed(); | 374 | state.framebuffer_srgb.enabled = OpenGLState::GetsRGBUsed(); |
| 377 | state.Apply(); | 375 | state.Apply(); |
| 378 | glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(vertices), vertices.data()); | 376 | glNamedBufferSubData(vertex_buffer.handle, 0, sizeof(vertices), vertices.data()); |
| 379 | glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); | 377 | glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); |
| 380 | // restore default state | 378 | // Restore default state |
| 381 | state.framebuffer_srgb.enabled = false; | 379 | state.framebuffer_srgb.enabled = false; |
| 382 | state.texture_units[0].texture = 0; | 380 | state.texture_units[0].texture = 0; |
| 383 | state.Apply(); | 381 | state.Apply(); |