Start work on GL state manager object

This commit is contained in:
wheremyfoodat 2023-07-04 23:26:18 +03:00
parent ee49f89779
commit b403e9a66e
8 changed files with 95 additions and 11 deletions

View file

@ -81,7 +81,7 @@ class GPU {
// Set to false by the renderer when the lighting_lut is uploaded ot the GPU
bool lightingLUTDirty = false;
GPU(Memory& mem);
GPU(Memory& mem, GLStateManager& gl);
void initGraphicsContext() { renderer.initGraphicsContext(); }
void getGraphicsContext() { renderer.getGraphicsContext(); }
void display() { renderer.display(); }

View file

@ -11,7 +11,7 @@
#include "crypto/aes_engine.hpp"
#include "io_file.hpp"
#include "memory.hpp"
#include "opengl.hpp"
#include "gl_state.hpp"
enum class ROMType { None, ELF, NCSD };
@ -22,6 +22,7 @@ class Emulator {
Kernel kernel;
Crypto::AESEngine aesEngine;
GLStateManager gl;
SDL_Window* window;
SDL_GLContext glContext;
SDL_GameController* gameController;
@ -56,5 +57,5 @@ class Emulator {
bool loadNCSD(const std::filesystem::path& path);
bool loadELF(const std::filesystem::path& path);
bool loadELF(std::ifstream& file);
void initGraphicsContext() { gpu.initGraphicsContext(); }
void initGraphicsContext();
};

58
include/gl_state.hpp Normal file
View file

@ -0,0 +1,58 @@
#pragma once
#include <type_traits>
#include "opengl.hpp"
// GL state manager object for use in the OpenGL GPU renderer and potentially other things in the future (such as a potential ImGui GUI)
// This object is meant to help us avoid duplicate OpenGL calls (such as binding the same program twice, enabling/disabling a setting twice, etc)
// by checking if we actually *need* a state change. This is meant to avoid expensive driver calls and minimize unneeded state changes
// A lot of code is in the header file instead of the relevant source file to make sure stuff gets inlined even without LTO, and
// because this header should ideally not be getting included in too many places
// Code that does not need inlining however, like the reset() function should be in gl_state.cpp
// This state manager may not handle every aspect of OpenGL, in which case anything not handled here should just be manipulated with raw
// OpenGL/opengl.hpp calls However, anything that can be handled through the state manager should, or at least there should be an attempt to keep it
// consistent with the current GL state to avoid bugs/suboptimal code.
// The state manager must *also* be a trivially constructible/destructible type, to ensure that no OpenGL functions get called sneakily without us
// knowing. This is important for when we want to eg add a Vulkan or misc backend. Would definitely not want to refactor all this. So we try to be as
// backend-agnostic as possible
struct GLStateManager {
bool blendEnabled;
bool depthEnabled;
void reset();
void resetBlend();
void resetDepth();
void enableDepth() {
if (!depthEnabled) {
depthEnabled = true;
OpenGL::enableDepth();
}
}
void disableDepth() {
if (depthEnabled) {
depthEnabled = false;
OpenGL::disableDepth();
}
}
void enableBlend() {
if (!blendEnabled) {
blendEnabled = true;
OpenGL::enableBlend();
}
}
void disableBlend() {
if (blendEnabled) {
blendEnabled = false;
OpenGL::disableBlend();
}
}
};
static_assert(std::is_trivially_constructible<GLStateManager>(), "OpenGL State Manager class is not trivially constructible!");
static_assert(std::is_trivially_destructible<GLStateManager>(), "OpenGL State Manager class is not trivially destructible!");

View file

@ -3,9 +3,9 @@
#include <span>
#include "PICA/float_types.hpp"
#include "gl_state.hpp"
#include "helpers.hpp"
#include "logger.hpp"
#include "opengl.hpp"
#include "surface_cache.hpp"
#include "textures.hpp"
#include "PICA/regs.hpp"
@ -16,6 +16,8 @@ class GPU;
class Renderer {
GPU& gpu;
GLStateManager& gl;
OpenGL::Program triangleProgram;
OpenGL::Program displayProgram;
@ -81,7 +83,7 @@ class Renderer {
void updateLightingLUT();
public:
Renderer(GPU& gpu, const std::array<u32, regNum>& internalRegs) : gpu(gpu), regs(internalRegs) {}
Renderer(GPU& gpu, GLStateManager& gl, const std::array<u32, regNum>& internalRegs) : gpu(gpu), gl(gl), regs(internalRegs) {}
void reset();
void display(); // Display the 3DS screen contents to the window