mirror of
				https://git.suyu.dev/suyu/suyu
				synced 2025-11-04 08:59:03 -06:00 
			
		
		
		
	gl_state: Remove program tracking
This commit is contained in:
		@@ -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<GLShader::ProgramManager>();
 | 
			
		||||
    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;
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -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<GLShader::ProgramManager> shader_program_manager;
 | 
			
		||||
    GLShader::ProgramManager& program_manager;
 | 
			
		||||
 | 
			
		||||
    static constexpr std::size_t STREAM_BUFFER_SIZE = 128 * 1024 * 1024;
 | 
			
		||||
    OGLBufferCache buffer_cache;
 | 
			
		||||
 
 | 
			
		||||
@@ -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;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -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);
 | 
			
		||||
 
 | 
			
		||||
@@ -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;
 | 
			
		||||
 
 | 
			
		||||
@@ -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
 | 
			
		||||
 
 | 
			
		||||
@@ -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;
 | 
			
		||||
};
 | 
			
		||||
 
 | 
			
		||||
@@ -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<RasterizerOpenGL>(system, emu_window, screen_info);
 | 
			
		||||
    rasterizer =
 | 
			
		||||
        std::make_unique<RasterizerOpenGL>(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<float>(layout.width), static_cast<float>(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);
 | 
			
		||||
 
 | 
			
		||||
@@ -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<u8> gl_framebuffer_data;
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user