From 1c4bf9cbfa4e4303890f73be11eb1dee88d070fe Mon Sep 17 00:00:00 2001 From: ReinUsesLisp Date: Thu, 26 Dec 2019 16:04:41 -0300 Subject: [PATCH] gl_state: Remove program tracking --- .../renderer_opengl/gl_rasterizer.cpp | 28 ++++++-------- .../renderer_opengl/gl_rasterizer.h | 5 +-- .../renderer_opengl/gl_resource_manager.cpp | 2 - .../renderer_opengl/gl_shader_manager.cpp | 18 +++------ .../renderer_opengl/gl_shader_manager.h | 17 ++++----- src/video_core/renderer_opengl/gl_state.cpp | 32 +--------------- src/video_core/renderer_opengl/gl_state.h | 12 ------ .../renderer_opengl/renderer_opengl.cpp | 37 +++++++++++++++---- .../renderer_opengl/renderer_opengl.h | 7 +++- 9 files changed, 63 insertions(+), 95 deletions(-) diff --git a/src/video_core/renderer_opengl/gl_rasterizer.cpp b/src/video_core/renderer_opengl/gl_rasterizer.cpp index b826146fbb..84c4d110c1 100644 --- a/src/video_core/renderer_opengl/gl_rasterizer.cpp +++ b/src/video_core/renderer_opengl/gl_rasterizer.cpp @@ -99,14 +99,11 @@ void oglEnablei(GLenum cap, bool state, GLuint index) { } // Anonymous namespace RasterizerOpenGL::RasterizerOpenGL(Core::System& system, Core::Frontend::EmuWindow& emu_window, - ScreenInfo& info) + ScreenInfo& info, GLShader::ProgramManager& program_manager) : RasterizerAccelerated{system.Memory()}, texture_cache{system, *this, device}, shader_cache{*this, system, emu_window, device}, query_cache{system, *this}, system{system}, - screen_info{info}, buffer_cache{*this, system, device, STREAM_BUFFER_SIZE} { - shader_program_manager = std::make_unique(); - state.draw.shader_program = 0; - state.Apply(); - + screen_info{info}, program_manager{program_manager}, buffer_cache{*this, system, device, + STREAM_BUFFER_SIZE} { CheckExtensions(); } @@ -228,10 +225,10 @@ void RasterizerOpenGL::SetupShaders(GLenum primitive_mode) { if (!gpu.regs.IsShaderConfigEnabled(index)) { switch (program) { case Maxwell::ShaderProgram::Geometry: - shader_program_manager->UseTrivialGeometryShader(); + program_manager.UseGeometryShader(0); break; case Maxwell::ShaderProgram::Fragment: - shader_program_manager->UseTrivialFragmentShader(); + program_manager.UseFragmentShader(0); break; default: break; @@ -262,13 +259,13 @@ void RasterizerOpenGL::SetupShaders(GLenum primitive_mode) { switch (program) { case Maxwell::ShaderProgram::VertexA: case Maxwell::ShaderProgram::VertexB: - shader_program_manager->UseProgrammableVertexShader(program_handle); + program_manager.UseVertexShader(program_handle); break; case Maxwell::ShaderProgram::Geometry: - shader_program_manager->UseProgrammableGeometryShader(program_handle); + program_manager.UseGeometryShader(program_handle); break; case Maxwell::ShaderProgram::Fragment: - shader_program_manager->UseProgrammableFragmentShader(program_handle); + program_manager.UseFragmentShader(program_handle); break; default: UNIMPLEMENTED_MSG("Unimplemented shader index={}, enable={}, offset=0x{:08X}", index, @@ -550,7 +547,7 @@ void RasterizerOpenGL::Draw(bool is_indexed, bool is_instanced) { bind_ubo_pushbuffer.Bind(); bind_ssbo_pushbuffer.Bind(); - shader_program_manager->ApplyTo(state); + program_manager.Update(); state.Apply(); if (texture_cache.TextureBarrier()) { @@ -613,8 +610,8 @@ void RasterizerOpenGL::DispatchCompute(GPUVAddr code_addr) { const ProgramVariant variant(launch_desc.block_dim_x, launch_desc.block_dim_y, launch_desc.block_dim_z, launch_desc.shared_alloc, launch_desc.local_pos_alloc); - state.draw.shader_program = kernel->GetHandle(variant); - state.draw.program_pipeline = 0; + glUseProgramStages(program_manager.GetHandle(), GL_COMPUTE_SHADER_BIT, + kernel->GetHandle(variant)); const std::size_t buffer_size = Tegra::Engines::KeplerCompute::NumConstBuffers * @@ -632,9 +629,6 @@ void RasterizerOpenGL::DispatchCompute(GPUVAddr code_addr) { bind_ubo_pushbuffer.Bind(); bind_ssbo_pushbuffer.Bind(); - state.ApplyShaderProgram(); - state.ApplyProgramPipeline(); - glDispatchCompute(launch_desc.grid_dim_x, launch_desc.grid_dim_y, launch_desc.grid_dim_z); ++num_queued_commands; } diff --git a/src/video_core/renderer_opengl/gl_rasterizer.h b/src/video_core/renderer_opengl/gl_rasterizer.h index de21a35114..b8158c152f 100644 --- a/src/video_core/renderer_opengl/gl_rasterizer.h +++ b/src/video_core/renderer_opengl/gl_rasterizer.h @@ -55,7 +55,7 @@ struct DrawParameters; class RasterizerOpenGL : public VideoCore::RasterizerAccelerated { public: explicit RasterizerOpenGL(Core::System& system, Core::Frontend::EmuWindow& emu_window, - ScreenInfo& info); + ScreenInfo& info, GLShader::ProgramManager& program_manager); ~RasterizerOpenGL() override; void Draw(bool is_indexed, bool is_instanced) override; @@ -218,8 +218,7 @@ private: Core::System& system; ScreenInfo& screen_info; - - std::unique_ptr shader_program_manager; + GLShader::ProgramManager& program_manager; 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 21ea6fde46..404fd65567 100644 --- a/src/video_core/renderer_opengl/gl_resource_manager.cpp +++ b/src/video_core/renderer_opengl/gl_resource_manager.cpp @@ -123,7 +123,6 @@ void OGLProgram::Release() { MICROPROFILE_SCOPE(OpenGL_ResourceDeletion); glDeleteProgram(handle); - OpenGLState::GetCurState().ResetProgram(handle).Apply(); handle = 0; } @@ -141,7 +140,6 @@ void OGLPipeline::Release() { MICROPROFILE_SCOPE(OpenGL_ResourceDeletion); glDeleteProgramPipelines(1, &handle); - OpenGLState::GetCurState().ResetPipeline(handle).Apply(); handle = 0; } diff --git a/src/video_core/renderer_opengl/gl_shader_manager.cpp b/src/video_core/renderer_opengl/gl_shader_manager.cpp index 75d3fac042..15f3cd0669 100644 --- a/src/video_core/renderer_opengl/gl_shader_manager.cpp +++ b/src/video_core/renderer_opengl/gl_shader_manager.cpp @@ -10,27 +10,21 @@ namespace OpenGL::GLShader { using Tegra::Engines::Maxwell3D; -ProgramManager::ProgramManager() { +ProgramManager::~ProgramManager() = default; + +void ProgramManager::Create() { pipeline.Create(); } -ProgramManager::~ProgramManager() = default; - -void ProgramManager::ApplyTo(OpenGLState& state) { - UpdatePipeline(); - state.draw.shader_program = 0; - state.draw.program_pipeline = pipeline.handle; -} - -void ProgramManager::UpdatePipeline() { +void ProgramManager::Update() { // Avoid updating the pipeline when values have no changed if (old_state == current_state) { return; } // Workaround for AMD bug - constexpr GLenum all_used_stages{GL_VERTEX_SHADER_BIT | GL_GEOMETRY_SHADER_BIT | - GL_FRAGMENT_SHADER_BIT}; + static constexpr GLenum all_used_stages{GL_VERTEX_SHADER_BIT | GL_GEOMETRY_SHADER_BIT | + GL_FRAGMENT_SHADER_BIT}; glUseProgramStages(pipeline.handle, all_used_stages, 0); glUseProgramStages(pipeline.handle, GL_VERTEX_SHADER_BIT, current_state.vertex_shader); diff --git a/src/video_core/renderer_opengl/gl_shader_manager.h b/src/video_core/renderer_opengl/gl_shader_manager.h index 478c165ce9..db23a27e85 100644 --- a/src/video_core/renderer_opengl/gl_shader_manager.h +++ b/src/video_core/renderer_opengl/gl_shader_manager.h @@ -29,25 +29,26 @@ static_assert(sizeof(MaxwellUniformData) < 16384, class ProgramManager { public: - explicit ProgramManager(); ~ProgramManager(); - void ApplyTo(OpenGLState& state); + void Create(); - void UseProgrammableVertexShader(GLuint program) { + void Update(); + + void UseVertexShader(GLuint program) { current_state.vertex_shader = program; } - void UseProgrammableGeometryShader(GLuint program) { + void UseGeometryShader(GLuint program) { current_state.geometry_shader = program; } - void UseProgrammableFragmentShader(GLuint program) { + void UseFragmentShader(GLuint program) { current_state.fragment_shader = program; } - void UseTrivialGeometryShader() { - current_state.geometry_shader = 0; + GLuint GetHandle() const { + return pipeline.handle; } void UseTrivialFragmentShader() { @@ -70,8 +71,6 @@ private: GLuint geometry_shader{}; }; - void UpdatePipeline(); - OGLPipeline pipeline; PipelineState current_state; PipelineState old_state; diff --git a/src/video_core/renderer_opengl/gl_state.cpp b/src/video_core/renderer_opengl/gl_state.cpp index be4ca6bf01..e8a23d41d0 100644 --- a/src/video_core/renderer_opengl/gl_state.cpp +++ b/src/video_core/renderer_opengl/gl_state.cpp @@ -85,36 +85,6 @@ void Enable(GLenum cap, GLuint index, bool& current_value, bool new_value) { OpenGLState::OpenGLState() = default; -void OpenGLState::ApplyShaderProgram() { - if (UpdateValue(cur_state.draw.shader_program, draw.shader_program)) { - glUseProgram(draw.shader_program); - } -} - -void OpenGLState::ApplyProgramPipeline() { - if (UpdateValue(cur_state.draw.program_pipeline, draw.program_pipeline)) { - glBindProgramPipeline(draw.program_pipeline); - } -} - -void OpenGLState::Apply() { - MICROPROFILE_SCOPE(OpenGL_State); - ApplyShaderProgram(); - ApplyProgramPipeline(); -} - -OpenGLState& OpenGLState::ResetProgram(GLuint handle) { - if (draw.shader_program == handle) { - draw.shader_program = 0; - } - return *this; -} - -OpenGLState& OpenGLState::ResetPipeline(GLuint handle) { - if (draw.program_pipeline == handle) { - draw.program_pipeline = 0; - } - return *this; -} +void OpenGLState::Apply() {} } // namespace OpenGL diff --git a/src/video_core/renderer_opengl/gl_state.h b/src/video_core/renderer_opengl/gl_state.h index c9a8397362..f62e2e2e19 100644 --- a/src/video_core/renderer_opengl/gl_state.h +++ b/src/video_core/renderer_opengl/gl_state.h @@ -13,11 +13,6 @@ namespace OpenGL { class OpenGLState { public: - struct { - GLuint shader_program = 0; // GL_CURRENT_PROGRAM - GLuint program_pipeline = 0; // GL_PROGRAM_PIPELINE_BINDING - } draw; - OpenGLState(); /// Get the currently active OpenGL state @@ -28,13 +23,6 @@ public: /// Apply this state as the current OpenGL state void Apply(); - void ApplyShaderProgram(); - void ApplyProgramPipeline(); - - /// Resets any references to the given resource - OpenGLState& ResetProgram(GLuint handle); - OpenGLState& ResetPipeline(GLuint handle); - private: static OpenGLState cur_state; }; diff --git a/src/video_core/renderer_opengl/renderer_opengl.cpp b/src/video_core/renderer_opengl/renderer_opengl.cpp index da4b4bf342..ace3aec882 100644 --- a/src/video_core/renderer_opengl/renderer_opengl.cpp +++ b/src/video_core/renderer_opengl/renderer_opengl.cpp @@ -20,6 +20,7 @@ #include "core/telemetry_session.h" #include "video_core/morton.h" #include "video_core/renderer_opengl/gl_rasterizer.h" +#include "video_core/renderer_opengl/gl_shader_manager.h" #include "video_core/renderer_opengl/renderer_opengl.h" namespace OpenGL { @@ -158,9 +159,13 @@ public: namespace { -constexpr char vertex_shader[] = R"( +constexpr char VERTEX_SHADER[] = R"( #version 430 core +out gl_PerVertex { + vec4 gl_Position; +}; + layout (location = 0) in vec2 vert_position; layout (location = 1) in vec2 vert_tex_coord; layout (location = 0) out vec2 frag_tex_coord; @@ -181,7 +186,7 @@ void main() { } )"; -constexpr char fragment_shader[] = R"( +constexpr char FRAGMENT_SHADER[] = R"( #version 430 core layout (location = 0) in vec2 frag_tex_coord; @@ -426,10 +431,19 @@ void RendererOpenGL::InitOpenGLObjects() { glClearColor(Settings::values.bg_red, Settings::values.bg_green, Settings::values.bg_blue, 0.0f); - // Link shaders and get variable locations - shader.CreateFromSource(vertex_shader, nullptr, fragment_shader); - state.draw.shader_program = shader.handle; - state.Apply(); + // Create shader programs + OGLShader vertex_shader; + vertex_shader.Create(VERTEX_SHADER, GL_VERTEX_SHADER); + + OGLShader fragment_shader; + fragment_shader.Create(FRAGMENT_SHADER, GL_FRAGMENT_SHADER); + + vertex_program.Create(true, false, vertex_shader.handle); + fragment_program.Create(true, false, fragment_shader.handle); + + // Create program pipeline + program_manager.Create(); + glBindProgramPipeline(program_manager.GetHandle()); // Generate VBO handle for drawing vertex_buffer.Create(); @@ -468,7 +482,8 @@ void RendererOpenGL::CreateRasterizer() { if (rasterizer) { return; } - rasterizer = std::make_unique(system, emu_window, screen_info); + rasterizer = + std::make_unique(system, emu_window, screen_info, program_manager); } void RendererOpenGL::ConfigureFramebufferTexture(TextureInfo& texture, @@ -517,7 +532,8 @@ void RendererOpenGL::DrawScreen(const Layout::FramebufferLayout& layout) { // Set projection matrix const std::array ortho_matrix = MakeOrthographicMatrix(static_cast(layout.width), static_cast(layout.height)); - glUniformMatrix3x2fv(ModelViewMatrixLocation, 1, GL_FALSE, ortho_matrix.data()); + glProgramUniformMatrix3x2fv(vertex_program.handle, ModelViewMatrixLocation, 1, GL_FALSE, + std::data(ortho_matrix)); const auto& texcoords = screen_info.display_texcoords; auto left = texcoords.left; @@ -562,6 +578,11 @@ void RendererOpenGL::DrawScreen(const Layout::FramebufferLayout& layout) { state.Apply(); // TODO: Signal state tracker about these changes + program_manager.UseVertexShader(vertex_program.handle); + program_manager.UseGeometryShader(0); + program_manager.UseFragmentShader(fragment_program.handle); + program_manager.Update(); + glEnable(GL_CULL_FACE); if (screen_info.display_srgb) { glEnable(GL_FRAMEBUFFER_SRGB); diff --git a/src/video_core/renderer_opengl/renderer_opengl.h b/src/video_core/renderer_opengl/renderer_opengl.h index 42a2141d85..f1225269f2 100644 --- a/src/video_core/renderer_opengl/renderer_opengl.h +++ b/src/video_core/renderer_opengl/renderer_opengl.h @@ -10,6 +10,7 @@ #include "common/math_util.h" #include "video_core/renderer_base.h" #include "video_core/renderer_opengl/gl_resource_manager.h" +#include "video_core/renderer_opengl/gl_shader_manager.h" #include "video_core/renderer_opengl/gl_state.h" namespace Core { @@ -95,12 +96,16 @@ private: // OpenGL object IDs OGLBuffer vertex_buffer; - OGLProgram shader; + OGLProgram vertex_program; + OGLProgram fragment_program; OGLFramebuffer screenshot_framebuffer; /// Display information for Switch screen ScreenInfo screen_info; + /// Global dummy shader pipeline + GLShader::ProgramManager program_manager; + /// OpenGL framebuffer data std::vector gl_framebuffer_data;