mirror of
https://github.com/wheremyfoodat/Panda3DS.git
synced 2025-04-20 12:39:13 +12:00
Actually implement the damn thing
This commit is contained in:
parent
c396b3f225
commit
67069a8826
7 changed files with 274 additions and 21 deletions
|
@ -206,6 +206,24 @@ namespace PICA {
|
|||
return std::memcmp(this, &config, sizeof(FragmentConfig)) == 0;
|
||||
}
|
||||
|
||||
FragmentConfig& operator=(const FragmentConfig& config) {
|
||||
// BitField copy constructor is deleted for reasons, so we have to do this manually
|
||||
outConfig.raw = config.outConfig.raw;
|
||||
texConfig = config.texConfig;
|
||||
fogConfig.raw = config.fogConfig.raw;
|
||||
lighting.raw = config.lighting.raw;
|
||||
for (int i = 0; i < 7; i++) {
|
||||
lighting.luts[i].raw = config.lighting.luts[i].raw;
|
||||
}
|
||||
for (int i = 0; i < 8; i++) {
|
||||
lighting.lights[i].raw = config.lighting.lights[i].raw;
|
||||
}
|
||||
|
||||
// If this fails you probably added a new field to the struct and forgot to update the copy constructor
|
||||
static_assert(sizeof(FragmentConfig) == sizeof(outConfig.raw) + sizeof(texConfig) + sizeof(fogConfig.raw) + sizeof(lighting.raw) + 7 * sizeof(LightingLUTConfig) + 8 * sizeof(Light));
|
||||
return *this;
|
||||
}
|
||||
|
||||
FragmentConfig(const std::array<u32, 0x300>& regs) : lighting(regs) {
|
||||
auto alphaTestConfig = regs[InternalRegs::AlphaTestConfig];
|
||||
auto alphaTestFunction = Helpers::getBits<4, 3>(alphaTestConfig);
|
||||
|
|
54
include/renderer_gl/async_compiler.hpp
Normal file
54
include/renderer_gl/async_compiler.hpp
Normal file
|
@ -0,0 +1,54 @@
|
|||
#pragma once
|
||||
|
||||
#include <atomic>
|
||||
#include <thread>
|
||||
|
||||
#include "opengl.hpp"
|
||||
#include "renderer_gl/renderer_gl.hpp"
|
||||
#include "PICA/pica_frag_config.hpp"
|
||||
#include "lockfree/spsc/queue.hpp"
|
||||
|
||||
namespace PICA::ShaderGen
|
||||
{
|
||||
class FragmentGenerator;
|
||||
}
|
||||
|
||||
namespace AsyncCompiler
|
||||
{
|
||||
void* createContext(void* userdata);
|
||||
void makeCurrent(void* userdata, void* context);
|
||||
void destroyContext(void* context);
|
||||
}
|
||||
|
||||
struct CompilingProgram
|
||||
{
|
||||
CachedProgram* program;
|
||||
PICA::FragmentConfig* config;
|
||||
};
|
||||
|
||||
struct AsyncCompilerThread
|
||||
{
|
||||
explicit AsyncCompilerThread(PICA::ShaderGen::FragmentGenerator& fragShaderGen, void* userdata);
|
||||
~AsyncCompilerThread();
|
||||
|
||||
// Called from the emulator thread to queue a fragment configuration for compilation
|
||||
// Returns false if the queue is full, true otherwise
|
||||
void PushFragmentConfig(const PICA::FragmentConfig& config, CachedProgram* cachedProgram);
|
||||
|
||||
// Wait for all queued fragment configurations to be compiled
|
||||
void Finish();
|
||||
|
||||
private:
|
||||
PICA::ShaderGen::FragmentGenerator& fragShaderGen;
|
||||
OpenGL::Shader defaultShadergenVs;
|
||||
|
||||
// Our lockfree queue only allows for trivial types, so we preallocate enough structs
|
||||
// to avoid dynamic allocation on each push
|
||||
int preallocatedProgramsIndex;
|
||||
static constexpr int preallocatedProgramsSize = 256;
|
||||
std::array<CompilingProgram*, preallocatedProgramsSize> preallocatedPrograms;
|
||||
lockfree::spsc::Queue<CompilingProgram*, preallocatedProgramsSize - 1> programQueue;
|
||||
std::atomic_bool running;
|
||||
std::atomic_flag hasWork = ATOMIC_FLAG_INIT;
|
||||
std::thread thread;
|
||||
};
|
|
@ -23,6 +23,15 @@
|
|||
// More circular dependencies!
|
||||
class GPU;
|
||||
|
||||
// Cached recompiled fragment shader
|
||||
struct CachedProgram {
|
||||
OpenGL::Program program;
|
||||
std::atomic_bool compiling = false;
|
||||
bool needsInitialization = true;
|
||||
};
|
||||
|
||||
struct AsyncCompilerThread;
|
||||
|
||||
class RendererGL final : public Renderer {
|
||||
GLStateManager gl = {};
|
||||
|
||||
|
@ -72,12 +81,10 @@ class RendererGL final : public Renderer {
|
|||
OpenGL::Shader defaultShadergenVs;
|
||||
GLuint shadergenFragmentUBO;
|
||||
|
||||
// Cached recompiled fragment shader
|
||||
struct CachedProgram {
|
||||
OpenGL::Program program;
|
||||
};
|
||||
std::unordered_map<PICA::FragmentConfig, CachedProgram> shaderCache;
|
||||
|
||||
AsyncCompilerThread* asyncCompiler = nullptr;
|
||||
|
||||
OpenGL::Framebuffer getColourFBO();
|
||||
OpenGL::Texture getTexture(Texture& tex);
|
||||
OpenGL::Program& getSpecializedShader();
|
||||
|
@ -101,7 +108,6 @@ class RendererGL final : public Renderer {
|
|||
|
||||
void reset() override;
|
||||
void display() override; // Display the 3DS screen contents to the window
|
||||
void initGraphicsContext(SDL_Window* window) override; // Initialize graphics context
|
||||
void clearBuffer(u32 startAddress, u32 endAddress, u32 value, u32 control) override; // Clear a GPU buffer in VRAM
|
||||
void displayTransfer(u32 inputAddr, u32 outputAddr, u32 inputSize, u32 outputSize, u32 flags) override; // Perform display transfer
|
||||
void textureCopy(u32 inputAddr, u32 outputAddr, u32 totalBytes, u32 inputSize, u32 outputSize, u32 flags) override;
|
||||
|
@ -123,7 +129,9 @@ class RendererGL final : public Renderer {
|
|||
void initUbershader(OpenGL::Program& program);
|
||||
|
||||
#ifdef PANDA3DS_FRONTEND_QT
|
||||
virtual void initGraphicsContext([[maybe_unused]] GL::Context* context) override { initGraphicsContextInternal(); }
|
||||
virtual void initGraphicsContext(GL::Context* context) override;
|
||||
#elif defined(PANDA3DS_FRONTEND_SDL)
|
||||
virtual void initGraphicsContext(SDL_Window* window) override;
|
||||
#endif
|
||||
|
||||
// Take a screenshot of the screen and store it in a file
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue