mirror of
https://github.com/wheremyfoodat/Panda3DS.git
synced 2025-07-15 19:57:08 +12:00
GLES: Implement logic ops via fb fetch
This commit is contained in:
parent
96f684e51c
commit
511e05becf
8 changed files with 89 additions and 6 deletions
|
@ -1,6 +1,10 @@
|
|||
#include "PICA/pica_frag_config.hpp"
|
||||
#include "PICA/regs.hpp"
|
||||
#include "PICA/shader_gen.hpp"
|
||||
|
||||
// We can include the driver headers here since they shouldn't have any actual API-specific code
|
||||
#include "renderer_gl/gl_driver.hpp"
|
||||
|
||||
using namespace PICA;
|
||||
using namespace PICA::ShaderGen;
|
||||
|
||||
|
@ -94,7 +98,7 @@ std::string FragmentGenerator::getDefaultVertexShader() {
|
|||
return ret;
|
||||
}
|
||||
|
||||
std::string FragmentGenerator::generate(const FragmentConfig& config) {
|
||||
std::string FragmentGenerator::generate(const FragmentConfig& config, void* driverInfo) {
|
||||
std::string ret = "";
|
||||
|
||||
switch (api) {
|
||||
|
@ -103,6 +107,14 @@ std::string FragmentGenerator::generate(const FragmentConfig& config) {
|
|||
default: break;
|
||||
}
|
||||
|
||||
// For GLES we need to enable & use the framebuffer fetch extension in order to emulate logic ops
|
||||
const bool emitLogicOps = api == API::GLES && config.outConfig.logicOpMode != PICA::LogicOpMode::Copy && driverInfo != nullptr &&
|
||||
static_cast<OpenGL::Driver*>(driverInfo)->supportsFbFetch;
|
||||
|
||||
if (emitLogicOps) {
|
||||
ret += "\n#extension GL_EXT_shader_framebuffer_fetch : require\n";
|
||||
}
|
||||
|
||||
bool unimplementedFlag = false;
|
||||
if (api == API::GLES) {
|
||||
ret += R"(
|
||||
|
@ -192,10 +204,13 @@ std::string FragmentGenerator::generate(const FragmentConfig& config) {
|
|||
}
|
||||
|
||||
compileFog(ret, config);
|
||||
|
||||
applyAlphaTest(ret, config);
|
||||
|
||||
ret += "fragColor = combinerOutput;\n}"; // End of main function
|
||||
if (!emitLogicOps) {
|
||||
ret += "fragColor = combinerOutput;\n}"; // End of main function
|
||||
} else {
|
||||
compileLogicOps(ret, config);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
@ -671,3 +686,28 @@ void FragmentGenerator::compileFog(std::string& shader, const PICA::FragmentConf
|
|||
shader += "float fog_factor = clamp(value.r + value.g * delta, 0.0, 1.0);";
|
||||
shader += "combinerOutput.rgb = mix(fog_color, combinerOutput.rgb, fog_factor);";
|
||||
}
|
||||
|
||||
void FragmentGenerator::compileLogicOps(std::string& shader, const PICA::FragmentConfig& config) {
|
||||
if (api != API::GLES) [[unlikely]] {
|
||||
Helpers::warn("Shadergen: Unsupported API for compileLogicOps");
|
||||
shader += "fragColor = combinerOutput;\n}"; // End of main function
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
shader += "fragColor = ";
|
||||
switch (config.outConfig.logicOpMode) {
|
||||
case PICA::LogicOpMode::Copy: shader += "combinerOutput"; break;
|
||||
case PICA::LogicOpMode::Nop: shader += "gl_LastFragData[0]"; break;
|
||||
case PICA::LogicOpMode::Clear: shader += "vec4(0.0)"; break;
|
||||
case PICA::LogicOpMode::Set: shader += "vec4(uintBitsToFloat(0xFFFFFFFFu))"; break;
|
||||
case PICA::LogicOpMode::InvertedCopy: shader += "vec4(uvec4(combinerOutput * 255.0) ^ uvec4(0xFFu)) * (1.0 / 255.0)"; break;
|
||||
|
||||
default:
|
||||
shader += "combinerOutput";
|
||||
Helpers::warn("Shadergen: Unimplemented logic op mode");
|
||||
break;
|
||||
}
|
||||
|
||||
shader += ";\n}"; // End of main function
|
||||
}
|
|
@ -167,6 +167,9 @@ void RendererGL::initGraphicsContextInternal() {
|
|||
|
||||
reset();
|
||||
|
||||
// Populate our driver info structure
|
||||
driverInfo.supportsFbFetch = GLAD_GL_EXT_shader_framebuffer_fetch != 0;
|
||||
|
||||
// Initialize the default vertex shader used with shadergen
|
||||
std::string defaultShadergenVSSource = fragShaderGen.getDefaultVertexShader();
|
||||
defaultShadergenVs.create({defaultShadergenVSSource.c_str(), defaultShadergenVSSource.size()}, OpenGL::Vertex);
|
||||
|
@ -839,12 +842,16 @@ OpenGL::Program& RendererGL::getSpecializedShader() {
|
|||
constexpr uint uboBlockBinding = 2;
|
||||
|
||||
PICA::FragmentConfig fsConfig(regs);
|
||||
// If we're not on GLES, ignore the logic op configuration and don't generate redundant shaders for it, since we use hw logic ops
|
||||
#ifndef USING_GLES
|
||||
fsConfig.outConfig.logicOpMode = PICA::LogicOpMode(0);
|
||||
#endif
|
||||
|
||||
CachedProgram& programEntry = shaderCache[fsConfig];
|
||||
OpenGL::Program& program = programEntry.program;
|
||||
|
||||
if (!program.exists()) {
|
||||
std::string fs = fragShaderGen.generate(fsConfig);
|
||||
std::string fs = fragShaderGen.generate(fsConfig, &driverInfo);
|
||||
|
||||
OpenGL::Shader fragShader({fs.c_str(), fs.size()}, OpenGL::Fragment);
|
||||
program.create({defaultShadergenVs, fragShader});
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue