diff options
Diffstat (limited to 'src/video_core')
-rw-r--r-- | src/video_core/engines/maxwell_3d.cpp | 24 | ||||
-rw-r--r-- | src/video_core/engines/maxwell_3d.h | 5 | ||||
-rw-r--r-- | src/video_core/rasterizer_interface.h | 9 | ||||
-rw-r--r-- | src/video_core/renderer_opengl/gl_buffer_cache.cpp | 2 | ||||
-rw-r--r-- | src/video_core/renderer_opengl/gl_rasterizer.cpp | 93 | ||||
-rw-r--r-- | src/video_core/renderer_opengl/gl_rasterizer.h | 24 | ||||
-rw-r--r-- | src/video_core/renderer_opengl/gl_rasterizer_cache.cpp | 27 | ||||
-rw-r--r-- | src/video_core/renderer_opengl/gl_rasterizer_cache.h | 3 | ||||
-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 | 46 | ||||
-rw-r--r-- | src/video_core/renderer_opengl/renderer_opengl.h | 10 |
15 files changed, 169 insertions, 144 deletions
diff --git a/src/video_core/engines/maxwell_3d.cpp b/src/video_core/engines/maxwell_3d.cpp index 0ed7bc5d8..a388b3944 100644 --- a/src/video_core/engines/maxwell_3d.cpp +++ b/src/video_core/engines/maxwell_3d.cpp @@ -37,6 +37,7 @@ void Maxwell3D::InitializeRegisterDefaults() { regs.viewports[viewport].depth_range_near = 0.0f; regs.viewports[viewport].depth_range_far = 1.0f; } + // Doom and Bomberman seems to use the uninitialized registers and just enable blend // so initialize blend registers with sane values regs.blend.equation_rgb = Regs::Blend::Equation::Add; @@ -66,6 +67,7 @@ void Maxwell3D::InitializeRegisterDefaults() { regs.stencil_back_func_func = Regs::ComparisonOp::Always; regs.stencil_back_func_mask = 0xFFFFFFFF; regs.stencil_back_mask = 0xFFFFFFFF; + // TODO(Rodrigo): Most games do not set a point size. I think this is a case of a // register carrying a default value. Assume it's OpenGL's default (1). regs.point_size = 1.0f; @@ -78,6 +80,9 @@ void Maxwell3D::InitializeRegisterDefaults() { regs.color_mask[color_mask].B.Assign(1); regs.color_mask[color_mask].A.Assign(1); } + + // Commercial games seem to assume this value is enabled and nouveau sets this value manually. + regs.rt_separate_frag_data = 1; } void Maxwell3D::CallMacroMethod(u32 method, std::vector<u32> parameters) { @@ -135,6 +140,25 @@ void Maxwell3D::CallMethod(const GPU::MethodCall& method_call) { if (regs.reg_array[method_call.method] != method_call.argument) { regs.reg_array[method_call.method] = method_call.argument; + // Color buffers + constexpr u32 first_rt_reg = MAXWELL3D_REG_INDEX(rt); + constexpr u32 registers_per_rt = sizeof(regs.rt[0]) / sizeof(u32); + if (method_call.method >= first_rt_reg && + method_call.method < first_rt_reg + registers_per_rt * Regs::NumRenderTargets) { + const std::size_t rt_index = (method_call.method - first_rt_reg) / registers_per_rt; + dirty_flags.color_buffer |= 1u << static_cast<u32>(rt_index); + } + + // Zeta buffer + constexpr u32 registers_in_zeta = sizeof(regs.zeta) / sizeof(u32); + if (method_call.method == MAXWELL3D_REG_INDEX(zeta_enable) || + method_call.method == MAXWELL3D_REG_INDEX(zeta_width) || + method_call.method == MAXWELL3D_REG_INDEX(zeta_height) || + (method_call.method >= MAXWELL3D_REG_INDEX(zeta) && + method_call.method < MAXWELL3D_REG_INDEX(zeta) + registers_in_zeta)) { + dirty_flags.zeta_buffer = true; + } + // Shader constexpr u32 shader_registers_count = sizeof(regs.shader_config[0]) * Regs::MaxShaderProgram / sizeof(u32); diff --git a/src/video_core/engines/maxwell_3d.h b/src/video_core/engines/maxwell_3d.h index d50e5a126..1f76aa670 100644 --- a/src/video_core/engines/maxwell_3d.h +++ b/src/video_core/engines/maxwell_3d.h @@ -1089,12 +1089,17 @@ public: MemoryManager& memory_manager; struct DirtyFlags { + u8 color_buffer = 0xFF; + bool zeta_buffer = true; + bool shaders = true; bool vertex_attrib_format = true; u32 vertex_array = 0xFFFFFFFF; void OnMemoryWrite() { + color_buffer = 0xFF; + zeta_buffer = true; shaders = true; vertex_array = 0xFFFFFFFF; } diff --git a/src/video_core/rasterizer_interface.h b/src/video_core/rasterizer_interface.h index 06fc59dbe..ff5310848 100644 --- a/src/video_core/rasterizer_interface.h +++ b/src/video_core/rasterizer_interface.h @@ -4,6 +4,7 @@ #pragma once +#include <functional> #include "common/common_types.h" #include "video_core/engines/fermi_2d.h" #include "video_core/gpu.h" @@ -11,6 +12,14 @@ namespace VideoCore { +enum class LoadCallbackStage { + Prepare, + Decompile, + Build, + Complete, +}; +using DiskResourceLoadCallback = std::function<void(LoadCallbackStage, std::size_t, std::size_t)>; + class RasterizerInterface { public: virtual ~RasterizerInterface() {} 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 @@ namespace OpenGL { OGLBufferCache::OGLBufferCache(RasterizerOpenGL& rasterizer, std::size_t size) - : RasterizerCache{rasterizer}, stream_buffer(GL_ARRAY_BUFFER, size) {} + : RasterizerCache{rasterizer}, stream_buffer(size, true) {} GLintptr OGLBufferCache::UploadMemory(Tegra::GPUVAddr gpu_addr, std::size_t size, 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 97412590b..71829fee0 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() { } } -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()); + // 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(); + + 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 +167,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 +182,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 +222,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 +230,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; } @@ -365,7 +367,7 @@ void RasterizerOpenGL::SetupShaders(GLenum primitive_mode) { // (sometimes it's half the screen, sometimes three quarters). To avoid this, enable the // clip distances only when it's written by a shader stage. for (std::size_t i = 0; i < Maxwell::NumClipDistances; ++i) { - clip_distances[i] |= shader->GetShaderEntries().clip_distances[i]; + clip_distances[i] = clip_distances[i] || shader->GetShaderEntries().clip_distances[i]; } // When VertexA is enabled, we have dual vertex shaders @@ -488,17 +490,26 @@ void RasterizerOpenGL::ConfigureFramebuffers(OpenGLState& current_state, bool us bool using_depth_fb, bool preserve_contents, std::optional<std::size_t> single_color_target) { MICROPROFILE_SCOPE(OpenGL_Framebuffer); - const auto& regs = Core::System::GetInstance().GPU().Maxwell3D().regs; + const auto& gpu = Core::System::GetInstance().GPU().Maxwell3D(); + const auto& regs = gpu.regs; + + const FramebufferConfigState fb_config_state{using_color_fb, using_depth_fb, preserve_contents, + single_color_target}; + if (fb_config_state == current_framebuffer_config_state && gpu.dirty_flags.color_buffer == 0 && + !gpu.dirty_flags.zeta_buffer) { + // Only skip if the previous ConfigureFramebuffers call was from the same kind (multiple or + // single color targets). This is done because the guest registers may not change but the + // host framebuffer may contain different attachments + return; + } + current_framebuffer_config_state = fb_config_state; Surface depth_surface; if (using_depth_fb) { depth_surface = res_cache.GetDepthBufferSurface(preserve_contents); } - // TODO(bunnei): Figure out how the below register works. According to envytools, this should be - // used to enable multiple render targets. However, it is left unset on all games that I have - // tested. - UNIMPLEMENTED_IF(regs.rt_separate_frag_data != 0); + UNIMPLEMENTED_IF(regs.rt_separate_frag_data == 0); // Bind the framebuffer surfaces current_state.framebuffer_srgb.enabled = regs.framebuffer_srgb != 0; @@ -632,8 +643,6 @@ void RasterizerOpenGL::Clear() { return; } - ScopeAcquireGLContext acquire_context{emu_window}; - ConfigureFramebuffers(clear_state, use_color, use_depth || use_stencil, false, regs.clear_buffers.RT.Value()); if (regs.clear_flags.scissor) { @@ -667,8 +676,6 @@ void RasterizerOpenGL::DrawArrays() { auto& gpu = Core::System::GetInstance().GPU().Maxwell3D(); const auto& regs = gpu.regs; - ScopeAcquireGLContext acquire_context{emu_window}; - ConfigureFramebuffers(state); SyncColorMask(); SyncFragmentColorClampState(); @@ -691,9 +698,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) @@ -723,8 +727,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); diff --git a/src/video_core/renderer_opengl/gl_rasterizer.h b/src/video_core/renderer_opengl/gl_rasterizer.h index a53edee6d..21c51f874 100644 --- a/src/video_core/renderer_opengl/gl_rasterizer.h +++ b/src/video_core/renderer_opengl/gl_rasterizer.h @@ -99,6 +99,23 @@ private: float max_anisotropic = 1.0f; }; + struct FramebufferConfigState { + bool using_color_fb{}; + bool using_depth_fb{}; + bool preserve_contents{}; + std::optional<std::size_t> single_color_target; + + bool operator==(const FramebufferConfigState& rhs) const { + return std::tie(using_color_fb, using_depth_fb, preserve_contents, + single_color_target) == std::tie(rhs.using_color_fb, rhs.using_depth_fb, + rhs.preserve_contents, + rhs.single_color_target); + } + bool operator!=(const FramebufferConfigState& rhs) const { + return !operator==(rhs); + } + }; + /** * Configures the color and depth framebuffer states. * @param use_color_fb If true, configure color framebuffers. @@ -203,6 +220,7 @@ private: vertex_array_cache; std::map<FramebufferCacheKey, OGLFramebuffer> framebuffer_cache; + FramebufferConfigState current_framebuffer_config_state; std::array<SamplerInfo, Tegra::Engines::Maxwell3D::Regs::NumTextureSamplers> texture_samplers; @@ -215,8 +233,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(); diff --git a/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp b/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp index bff0c65cd..a05b8b936 100644 --- a/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp +++ b/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp @@ -919,9 +919,16 @@ Surface RasterizerCacheOpenGL::GetTextureSurface(const Tegra::Texture::FullTextu } Surface RasterizerCacheOpenGL::GetDepthBufferSurface(bool preserve_contents) { - const auto& regs{Core::System::GetInstance().GPU().Maxwell3D().regs}; + auto& gpu{Core::System::GetInstance().GPU().Maxwell3D()}; + const auto& regs{gpu.regs}; + + if (!gpu.dirty_flags.zeta_buffer) { + return last_depth_buffer; + } + gpu.dirty_flags.zeta_buffer = false; + if (!regs.zeta.Address() || !regs.zeta_enable) { - return {}; + return last_depth_buffer = {}; } SurfaceParams depth_params{SurfaceParams::CreateForDepthBuffer( @@ -929,25 +936,31 @@ Surface RasterizerCacheOpenGL::GetDepthBufferSurface(bool preserve_contents) { regs.zeta.memory_layout.block_width, regs.zeta.memory_layout.block_height, regs.zeta.memory_layout.block_depth, regs.zeta.memory_layout.type)}; - return GetSurface(depth_params, preserve_contents); + return last_depth_buffer = GetSurface(depth_params, preserve_contents); } Surface RasterizerCacheOpenGL::GetColorBufferSurface(std::size_t index, bool preserve_contents) { - const auto& regs{Core::System::GetInstance().GPU().Maxwell3D().regs}; + auto& gpu{Core::System::GetInstance().GPU().Maxwell3D()}; + const auto& regs{gpu.regs}; + + if ((gpu.dirty_flags.color_buffer & (1u << static_cast<u32>(index))) == 0) { + return last_color_buffers[index]; + } + gpu.dirty_flags.color_buffer &= ~(1u << static_cast<u32>(index)); ASSERT(index < Tegra::Engines::Maxwell3D::Regs::NumRenderTargets); if (index >= regs.rt_control.count) { - return {}; + return last_color_buffers[index] = {}; } if (regs.rt[index].Address() == 0 || regs.rt[index].format == Tegra::RenderTargetFormat::NONE) { - return {}; + return last_color_buffers[index] = {}; } const SurfaceParams color_params{SurfaceParams::CreateForFramebuffer(index)}; - return GetSurface(color_params, preserve_contents); + return last_color_buffers[index] = GetSurface(color_params, preserve_contents); } void RasterizerCacheOpenGL::LoadSurface(const Surface& surface) { diff --git a/src/video_core/renderer_opengl/gl_rasterizer_cache.h b/src/video_core/renderer_opengl/gl_rasterizer_cache.h index 7223700c4..37611c4fc 100644 --- a/src/video_core/renderer_opengl/gl_rasterizer_cache.h +++ b/src/video_core/renderer_opengl/gl_rasterizer_cache.h @@ -396,6 +396,9 @@ private: /// Use a Pixel Buffer Object to download the previous texture and then upload it to the new one /// using the new format. OGLBuffer copy_pbo; + + std::array<Surface, Tegra::Engines::Maxwell3D::Regs::NumRenderTargets> last_color_buffers; + Surface last_depth_buffer; }; } // namespace OpenGL 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() { 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() { 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() { draw.read_framebuffer = 0; draw.draw_framebuffer = 0; draw.vertex_array = 0; - draw.vertex_buffer = 0; - draw.uniform_buffer = 0; draw.shader_program = 0; draw.program_pipeline = 0; @@ -505,7 +503,6 @@ void OpenGLState::ApplySamplers() const { } void OpenGLState::ApplyFramebufferState() const { - // Framebuffer if (draw.read_framebuffer != cur_state.draw.read_framebuffer) { glBindFramebuffer(GL_READ_FRAMEBUFFER, draw.read_framebuffer); } @@ -514,16 +511,10 @@ void OpenGLState::ApplyFramebufferState() const { } } -void OpenGLState::ApplyVertexBufferState() const { - // Vertex array +void OpenGLState::ApplyVertexArrayState() const { 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 { @@ -543,11 +534,7 @@ void OpenGLState::ApplyDepthClamp() const { void OpenGLState::Apply() const { ApplyFramebufferState(); - ApplyVertexBufferState(); - // Uniform buffer - if (draw.uniform_buffer != cur_state.draw.uniform_buffer) { - glBindBuffer(GL_UNIFORM_BUFFER, draw.uniform_buffer); - } + ApplyVertexArrayState(); // Shader program if (draw.shader_program != cur_state.draw.shader_program) { @@ -638,16 +625,6 @@ OpenGLState& OpenGLState::ResetPipeline(GLuint handle) { return *this; } -OpenGLState& OpenGLState::ResetBuffer(GLuint handle) { - if (draw.vertex_buffer == handle) { - draw.vertex_buffer = 0; - } - if (draw.uniform_buffer == handle) { - draw.uniform_buffer = 0; - } - return *this; -} - OpenGLState& OpenGLState::ResetVertexArray(GLuint handle) { if (draw.vertex_array == handle) { 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: 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 uniform_buffer; // GL_UNIFORM_BUFFER_BINDING GLuint shader_program; // GL_CURRENT_PROGRAM GLuint program_pipeline; // GL_PROGRAM_PIPELINE_BINDING } draw; @@ -206,10 +204,10 @@ public: } /// Apply this state as the current OpenGL state void Apply() const; - /// Apply only the state afecting the framebuffer + /// Apply only the state affecting the framebuffer void ApplyFramebufferState() const; - /// Apply only the state afecting the vertex buffer - void ApplyVertexBufferState() const; + /// Apply only the state affecting the vertex array + void ApplyVertexArrayState() const; /// Set the initial OpenGL state static void ApplyDefaultState(); /// Resets any references to the given resource @@ -217,7 +215,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(); 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", namespace OpenGL { -OGLStreamBuffer::OGLStreamBuffer(GLenum target, GLsizeiptr size, bool prefer_coherent) - : gl_target(target), buffer_size(size) { +OGLStreamBuffer::OGLStreamBuffer(GLsizeiptr size, bool vertex_data_usage, bool prefer_coherent) + : buffer_size(size) { gl_buffer.Create(); - glBindBuffer(gl_target, gl_buffer.handle); GLsizeiptr allocate_size = size; - if (target == GL_ARRAY_BUFFER) { + if (vertex_data_usage) { // On AMD GPU there is a strange crash in indexed drawing. The crash happens when the buffer // read position is near the end and is an out-of-bound access to the vertex buffer. This is // 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 coherent = prefer_coherent; const GLbitfield flags = GL_MAP_WRITE_BIT | GL_MAP_PERSISTENT_BIT | (coherent ? GL_MAP_COHERENT_BIT : 0); - glBufferStorage(gl_target, allocate_size, nullptr, flags); - mapped_ptr = static_cast<u8*>(glMapBufferRange( - gl_target, 0, buffer_size, flags | (coherent ? 0 : GL_MAP_FLUSH_EXPLICIT_BIT))); + glNamedBufferStorage(gl_buffer.handle, allocate_size, nullptr, flags); + mapped_ptr = static_cast<u8*>(glMapNamedBufferRange( + gl_buffer.handle, 0, buffer_size, flags | (coherent ? 0 : GL_MAP_FLUSH_EXPLICIT_BIT))); } else { - glBufferData(gl_target, allocate_size, nullptr, GL_STREAM_DRAW); + glNamedBufferData(gl_buffer.handle, allocate_size, nullptr, GL_STREAM_DRAW); } } OGLStreamBuffer::~OGLStreamBuffer() { if (persistent) { - glBindBuffer(gl_target, gl_buffer.handle); - glUnmapBuffer(gl_target); + glUnmapNamedBuffer(gl_buffer.handle); } gl_buffer.Release(); } @@ -74,7 +72,7 @@ std::tuple<u8*, GLintptr, bool> OGLStreamBuffer::Map(GLsizeiptr size, GLintptr a invalidate = true; if (persistent) { - glUnmapBuffer(gl_target); + glUnmapNamedBuffer(gl_buffer.handle); } } @@ -84,7 +82,7 @@ std::tuple<u8*, GLintptr, bool> OGLStreamBuffer::Map(GLsizeiptr size, GLintptr a (coherent ? GL_MAP_COHERENT_BIT : GL_MAP_FLUSH_EXPLICIT_BIT) | (invalidate ? GL_MAP_INVALIDATE_BUFFER_BIT : GL_MAP_UNSYNCHRONIZED_BIT); mapped_ptr = static_cast<u8*>( - glMapBufferRange(gl_target, buffer_pos, buffer_size - buffer_pos, flags)); + glMapNamedBufferRange(gl_buffer.handle, buffer_pos, buffer_size - buffer_pos, flags)); mapped_offset = buffer_pos; } @@ -95,11 +93,11 @@ void OGLStreamBuffer::Unmap(GLsizeiptr size) { ASSERT(size <= mapped_size); if (!coherent && size > 0) { - glFlushMappedBufferRange(gl_target, buffer_pos - mapped_offset, size); + glFlushMappedNamedBufferRange(gl_buffer.handle, buffer_pos - mapped_offset, size); } if (!persistent) { - glUnmapBuffer(gl_target); + glUnmapNamedBuffer(gl_buffer.handle); } 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 { class OGLStreamBuffer : private NonCopyable { public: - explicit OGLStreamBuffer(GLenum target, GLsizeiptr size, bool prefer_coherent = false); + explicit OGLStreamBuffer(GLsizeiptr size, bool vertex_data_usage, bool prefer_coherent = false); ~OGLStreamBuffer(); GLuint GetHandle() const; @@ -33,7 +33,6 @@ public: private: OGLBuffer gl_buffer; - GLenum gl_target; bool coherent = false; 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..e37b65b38 100644 --- a/src/video_core/renderer_opengl/renderer_opengl.cpp +++ b/src/video_core/renderer_opengl/renderer_opengl.cpp @@ -14,6 +14,7 @@ #include "core/core.h" #include "core/core_timing.h" #include "core/frontend/emu_window.h" +#include "core/frontend/scope_acquire_window_context.h" #include "core/memory.h" #include "core/perf_stats.h" #include "core/settings.h" @@ -97,18 +98,6 @@ static std::array<GLfloat, 3 * 2> MakeOrthographicMatrix(const float width, cons return matrix; } -ScopeAcquireGLContext::ScopeAcquireGLContext(Core::Frontend::EmuWindow& emu_window_) - : emu_window{emu_window_} { - if (Settings::values.use_multi_core) { - emu_window.MakeCurrent(); - } -} -ScopeAcquireGLContext::~ScopeAcquireGLContext() { - if (Settings::values.use_multi_core) { - emu_window.DoneCurrent(); - } -} - RendererOpenGL::RendererOpenGL(Core::Frontend::EmuWindow& window) : VideoCore::RendererBase{window} {} @@ -117,7 +106,6 @@ RendererOpenGL::~RendererOpenGL() = default; /// Swap buffers (render frame) void RendererOpenGL::SwapBuffers( std::optional<std::reference_wrapper<const Tegra::FramebufferConfig>> framebuffer) { - ScopeAcquireGLContext acquire_context{render_window}; Core::System::GetInstance().GetPerfStats().EndSystemFrame(); @@ -245,20 +233,20 @@ void RendererOpenGL::InitOpenGLObjects() { // Generate VAO vertex_array.Create(); - state.draw.vertex_array = vertex_array.handle; - state.draw.vertex_buffer = vertex_buffer.handle; - state.draw.uniform_buffer = 0; - 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(); @@ -370,14 +358,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(); @@ -508,7 +494,7 @@ static void APIENTRY DebugHandler(GLenum source, GLenum type, GLuint id, GLenum /// Initialize the renderer bool RendererOpenGL::Init() { - ScopeAcquireGLContext acquire_context{render_window}; + Core::Frontend::ScopeAcquireWindowContext acquire_context{render_window}; if (GLAD_GL_KHR_debug) { glEnable(GL_DEBUG_OUTPUT); diff --git a/src/video_core/renderer_opengl/renderer_opengl.h b/src/video_core/renderer_opengl/renderer_opengl.h index b85cc262f..1665018db 100644 --- a/src/video_core/renderer_opengl/renderer_opengl.h +++ b/src/video_core/renderer_opengl/renderer_opengl.h @@ -39,16 +39,6 @@ struct ScreenInfo { TextureInfo texture; }; -/// Helper class to acquire/release OpenGL context within a given scope -class ScopeAcquireGLContext : NonCopyable { -public: - explicit ScopeAcquireGLContext(Core::Frontend::EmuWindow& window); - ~ScopeAcquireGLContext(); - -private: - Core::Frontend::EmuWindow& emu_window; -}; - class RendererOpenGL : public VideoCore::RendererBase { public: explicit RendererOpenGL(Core::Frontend::EmuWindow& window); |